1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2026-01-06 02:23:59 +00:00

Many improvements.

This commit is contained in:
Ylian Saint-Hilaire
2018-02-11 21:11:58 -08:00
parent 508646044e
commit 4b5c77b4fd
127 changed files with 51725 additions and 35030 deletions

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006 - 2017 Intel Corporation
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@ limitations under the License.
#include "ILibDuktapeModSearch.h"
#include "microstack/ILibParsers.h"
#include "microscript/ILibDuktape_Helpers.h"
#include "microscript/duk_module_duktape.h"
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(_MINCORE)
#define _CRTDBG_MAP_ALLOC
@@ -204,6 +204,8 @@ void ILibDuktape_ModSearch_Destroy(duk_context *ctx, void *user)
}
void ILibDuktape_ModSearch_Init(duk_context * ctx, void * chain, ILibSimpleDataStore mDB)
{
duk_module_duktape_init(ctx);
duk_push_heap_stash(ctx); // [stash]
duk_push_pointer(ctx, chain); // [stash][chain]
duk_put_prop_string(ctx, -2, ILibDuktape_Context_Chain); // [stash]

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006 - 2017 Intel Corporation
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -1,3 +1,19 @@
/*
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "ILibDuktape_ChildProcess.h"
#include "ILibDuktapeModSearch.h"
@@ -100,6 +116,7 @@ duk_ret_t ILibDuktape_ChildProcess_Kill(duk_context *ctx)
ILibDuktape_ChildProcess_SubProcess* ILibDuktape_ChildProcess_SpawnedProcess_PUSH(duk_context *ctx, ILibProcessPipe_Process mProcess, void *callback)
{
duk_push_object(ctx); // [ChildProcess]
ILibDuktape_WriteID(ctx, "childProcess.subProcess");
duk_push_pointer(ctx, mProcess); // [ChildProcess][ptr]
duk_put_prop_string(ctx, -2, ILibDuktape_ChildProcess_Process); // [ChildProcess]
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_ChildProcess_SubProcess)); // [ChildProcess][buffer]
@@ -121,21 +138,21 @@ ILibDuktape_ChildProcess_SubProcess* ILibDuktape_ChildProcess_SpawnedProcess_PUS
ILibDuktape_CreateInstanceMethod(ctx, "kill", ILibDuktape_ChildProcess_Kill, 0);
duk_push_object(ctx);
ILibDuktape_WriteID(ctx, "childProcess.stdout");
ILibDuktape_WriteID(ctx, "childProcess.subProcess.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");
ILibDuktape_WriteID(ctx, "childProcess.subProcess.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");
ILibDuktape_WriteID(ctx, "childProcess.subProcess.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);
@@ -231,6 +248,7 @@ duk_ret_t ILibDuktape_ChildProcess_execFile(duk_context *ctx)
void ILibDuktape_ChildProcess_PUSH(duk_context *ctx, void *chain)
{
duk_push_object(ctx);
ILibDuktape_WriteID(ctx, "childProcess");
duk_push_pointer(ctx, (void*)ILibProcessPipe_Manager_Create(chain));
duk_put_prop_string(ctx, -2, ILibDuktape_ChildProcess_Manager);
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_ChildProcess_Manager_Finalizer);

View File

@@ -1,3 +1,19 @@
/*
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef __ILIBDUKTAPE_CHILDPROCESS__
#define __ILIBDUKTAPE_CHILDPROCESS__

View File

@@ -1,3 +1,19 @@
/*
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(_MINCORE)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
@@ -38,7 +54,6 @@ typedef struct ILibDuktape_DGRAM_DATA
void *socketObject;
void *dgramObject;
void *chain;
void *OnClose, *OnError, *OnListening, *OnMessage, *OnSendOK;
ILibAsyncUDPSocket_SocketModule *mSocket;
}ILibDuktape_DGRAM_DATA;
typedef enum ILibDuktape_DGRAM_Config
@@ -68,34 +83,39 @@ void ILibDuktape_Dgram_Socket_OnData(ILibAsyncUDPSocket_SocketModule socketModul
ILibDuktape_DGRAM_DATA* ptrs = (ILibDuktape_DGRAM_DATA*)user;
if (ptrs != NULL && ptrs->ctx != NULL && ptrs->OnMessage != NULL)
if (ptrs != NULL && ptrs->ctx != NULL)
{
duk_push_heapptr(ptrs->ctx, ptrs->OnMessage); // [func]
duk_push_heapptr(ptrs->ctx, ptrs->socketObject); // [func][this]
duk_push_heapptr(ptrs->ctx, ptrs->socketObject); // [this]
duk_get_prop_string(ptrs->ctx, -1, "emit"); // [this][emit]
duk_swap_top(ptrs->ctx, -2); // [emit][this]
duk_push_string(ptrs->ctx, "message"); // [emit][this][message]
duk_push_external_buffer(ptrs->ctx);
duk_config_buffer(ptrs->ctx, -1, buffer, (duk_size_t)bufferLength); // [func][this][buffer]
duk_push_object(ptrs->ctx); // [func][this][buffer][rinfo]
duk_push_string(ptrs->ctx, remoteInterface->sin6_family == AF_INET ? "IPv4" : "IPv6"); // [func][this][buffer][rinfo][family]
duk_put_prop_string(ptrs->ctx, -2, "family"); // [func][this][buffer][rinfo]
duk_push_string(ptrs->ctx, ILibRemoteLogging_ConvertAddress((struct sockaddr*)remoteInterface)); // [func][this][buffer][rinfo][address]
duk_put_prop_string(ptrs->ctx, -2, "address"); // [func][this][buffer][rinfo]
duk_push_int(ptrs->ctx, (int)ntohs(remoteInterface->sin6_port)); // [func][this][buffer][rinfo][port]
duk_put_prop_string(ptrs->ctx, -2, "port"); // [func][this][buffer][rinfo]
duk_config_buffer(ptrs->ctx, -1, buffer, (duk_size_t)bufferLength); // [emit][this][message][buffer]
duk_push_object(ptrs->ctx); // [emit][this][message][buffer][rinfo]
duk_push_string(ptrs->ctx, remoteInterface->sin6_family == AF_INET ? "IPv4" : "IPv6"); // [emit][this][message][buffer][rinfo][family]
duk_put_prop_string(ptrs->ctx, -2, "family"); // [emit][this][message][buffer][rinfo]
duk_push_string(ptrs->ctx, ILibRemoteLogging_ConvertAddress((struct sockaddr*)remoteInterface)); // [emit][this][message][buffer][rinfo][address]
duk_put_prop_string(ptrs->ctx, -2, "address"); // [emit][this][message][buffer][rinfo]
duk_push_int(ptrs->ctx, (int)ntohs(remoteInterface->sin6_port)); // [emit][this][message][buffer][rinfo][port]
duk_put_prop_string(ptrs->ctx, -2, "port"); // [emit][this][message][buffer][rinfo]
duk_push_int(ptrs->ctx, bufferLength);
duk_put_prop_string(ptrs->ctx, -2, "size");
if (duk_pcall_method(ptrs->ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ptrs->ctx, "dgram.message() dispatch error"); }
if (duk_pcall_method(ptrs->ctx, 3) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ptrs->ctx, "dgram.message() dispatch error"); }
duk_pop(ptrs->ctx); // ...
}
}
void ILibDuktape_Dgram_Socket_OnSendOK(ILibAsyncUDPSocket_SocketModule socketModule, void *user1, void *user2)
{
ILibDuktape_DGRAM_DATA* ptrs = (ILibDuktape_DGRAM_DATA*)user1;
if (ptrs != NULL && ptrs->ctx != NULL && ptrs->OnSendOK != NULL)
if (ptrs != NULL && ptrs->ctx != NULL)
{
duk_push_heapptr(ptrs->ctx, ptrs->OnSendOK); // [func]
duk_push_heapptr(ptrs->ctx, ptrs->socketObject); // [func][this]
if (duk_pcall_method(ptrs->ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ptrs->ctx, "net.dgram.socket.onSendOk"); }
duk_push_heapptr(ptrs->ctx, ptrs->socketObject); // [this]
duk_get_prop_string(ptrs->ctx, -1, "emit"); // [this][emit]
duk_swap_top(ptrs->ctx, -2); // [emit][this]
duk_push_string(ptrs->ctx, "flushed"); // [emit][this][flushed]
if (duk_pcall_method(ptrs->ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ptrs->ctx, "net.dgram.socket.onSendOk"); }
duk_pop(ptrs->ctx); // ...
}
}
@@ -201,13 +221,14 @@ duk_ret_t ILibDuktape_DGram_Socket_bind(duk_context *ctx)
#endif
}
if (ptrs->OnListening != NULL)
{
duk_push_heapptr(ctx, ptrs->OnListening); // [func]
duk_push_heapptr(ctx, ptrs->socketObject); // [func][this]
if (duk_pcall_method(ctx, 0) != 0) { ILibDuktape_Process_UncaughtException(ctx); }
duk_pop(ctx); // ...
}
duk_push_heapptr(ctx, ptrs->socketObject); // [this]
duk_get_prop_string(ctx, -1, "emit"); // [this][emit]
duk_swap_top(ctx, -2); // [emit][this]
duk_push_string(ctx, "listening"); // [emit][this][listening]
if (duk_pcall_method(ctx, 1) != 0) { ILibDuktape_Process_UncaughtException(ctx); }
duk_pop(ctx); // ...
return 0;
}
@@ -352,12 +373,14 @@ duk_ret_t ILibDuktape_DGram_send(duk_context *ctx)
if (duk_pcall_method(ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "net.dgram.send.callback(): Error "); }
duk_pop(ctx); // ...
}
else if(ptrs->OnError != NULL)
else
{
duk_push_heapptr(ctx, ptrs->OnError); // [func]
duk_push_heapptr(ctx, ptrs->socketObject); // [func][this]
duk_push_heapptr(ctx, ptrs->socketObject); // [this]
duk_get_prop_string(ctx, -1, "emit"); // [this][emit]
duk_swap_top(ctx, -2); // [emit][this]
duk_push_string(ctx, "error"); // [emit][this][error]
duk_push_error_object(ctx, DUK_ERR_TYPE_ERROR, "net.dgram.send(): Attempted to send on a closed socket");
if (duk_pcall_method(ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "net.dgram.onError(): Error "); }
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "net.dgram.onError(): Error "); }
duk_pop(ctx); // ...
}
break;
@@ -433,11 +456,11 @@ duk_ret_t ILibDuktape_DGram_createSocket(duk_context *ctx)
ptrs->dgramObject = dgram;
ptrs->emitter = ILibDuktape_EventEmitter_Create(ctx);
ILibDuktape_EventEmitter_CreateEvent(ptrs->emitter, "close", &(ptrs->OnClose));
ILibDuktape_EventEmitter_CreateEvent(ptrs->emitter, "error", &(ptrs->OnError));
ILibDuktape_EventEmitter_CreateEvent(ptrs->emitter, "listening", &(ptrs->OnListening));
ILibDuktape_EventEmitter_CreateEvent(ptrs->emitter, "message", &(ptrs->OnMessage));
ILibDuktape_EventEmitter_CreateEvent(ptrs->emitter, "flushed", &(ptrs->OnSendOK));
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "close");
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "error");
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "listening");
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "message");
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "flushed");
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "config", config, "bind", ILibDuktape_DGram_Socket_bind, DUK_VARARGS);
@@ -459,6 +482,7 @@ duk_ret_t ILibDuktape_DGram_createSocket(duk_context *ctx)
void ILibDuktape_DGram_PUSH(duk_context *ctx, void *chain)
{
duk_push_object(ctx); // [dgram]
ILibDuktape_WriteID(ctx, "dgram");
duk_push_pointer(ctx, chain); // [dgram][chain]
duk_put_prop_string(ctx, -2, ILibDuktape_DGRAM_CHAIN); // [dgram]
ILibDuktape_CreateInstanceMethod(ctx, "createSocket", ILibDuktape_DGram_createSocket, DUK_VARARGS);

View File

@@ -1,3 +1,19 @@
/*
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef ___ILibDuktape_Dgram___
#define ___ILibDuktape_Dgram___

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006 - 2017 Intel Corporation
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006 - 2017 Intel Corporation
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -1,3 +1,19 @@
/*
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "duktape.h"
#include "ILibDuktape_Helpers.h"
#include "ILibParsers_Duktape.h"

View File

@@ -1,3 +1,19 @@
/*
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef __ILibDuktape_EncryptionStream__
#define __ILibDuktape_EncryptionStream__

View File

@@ -1,3 +1,19 @@
/*
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef __ILibDuktape_EVENT_EMITTER__
#define __ILibDuktape_EVENT_EMITTER__
@@ -22,17 +38,18 @@ ILibDuktape_EventEmitter* ILibDuktape_EventEmitter_GetEmitter_fromThis(duk_conte
ILibDuktape_EventEmitter* ILibDuktape_EventEmitter_GetEmitter_fromObject(duk_context *ctx, void *objHeapptr);
void ILibDuktape_EventEmitter_Init(duk_context *ctx);
void ILibDuktape_EventEmitter_RemoveAll(ILibDuktape_EventEmitter *emitter); // Removes all event handlers/dispatchers
int ILibDuktape_EventEmitter_GetEventCount(ILibDuktape_EventEmitter *emitter);
void ILibDuktape_EventEmitter_RemoveAllListeners(ILibDuktape_EventEmitter *emitter, char *eventName); // Invokes JavaScript method EventEmitter.removeAllListeners()
void ILibDuktape_EventEmitter_CreateEvent(ILibDuktape_EventEmitter *emitter, char *eventName, void **hptr); // Create Event with hybrid dispatcher
void ILibDuktape_EventEmitter_CreateEventEx(ILibDuktape_EventEmitter *emitter, char *eventName); // Create Event with virtual dispatcher
void ILibDuktape_EventEmitter_RemoveEventHeapptr(ILibDuktape_EventEmitter *emitter, char *eventName, void **heapptr); // Remove native callback pointer
int ILibDuktape_EventEmitter_AddEventHeapptr(ILibDuktape_EventEmitter *emitter, char *eventName, void **heapptr); // Add Callback after the fact
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_AddOnceEx3(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func);
int ILibDuktape_EventEmitter_PrependOnce(duk_context *ctx, duk_idx_t i, char *eventName, duk_c_function func);
int ILibDuktape_EventEmitter_HasListeners(ILibDuktape_EventEmitter *emitter, char *eventName);
#define ILibDuktape_EventEmitter_HasListenersEx(ctx, idx, eventName) ILibDuktape_EventEmitter_HasListeners(ILibDuktape_EventEmitter_GetEmitter(ctx, idx), eventName)
#define ILibDuktape_EventEmitter_AddOnceEx2(ctx, idx, eventName, func, argCount) ILibDuktape_EventEmitter_AddOnceEx3(ctx, idx, eventName, func)
#define ILibDuktape_EventEmitter_SetupEmit(ctx, heapptr, eventName) duk_push_heapptr((ctx), heapptr);duk_get_prop_string((ctx), -1, "emit");duk_swap_top((ctx), -2);duk_push_string((ctx), eventName)
int ILibDuktape_EventEmitter_AddOn(ILibDuktape_EventEmitter *emitter, char *eventName, void *heapptr); // Add native event handler
int ILibDuktape_EventEmitter_AddOnEx(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func);

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006 - 2017 Intel Corporation
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006 - 2017 Intel Corporation
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -1,3 +1,19 @@
/*
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "ILibDuktape_HECI.h"
#include "ILibDuktapeModSearch.h"
#include "ILibDuktape_Helpers.h"
@@ -220,7 +236,7 @@ duk_ret_t ILibDuktape_HECI_SessionFinalizer(duk_context *ctx)
void ILibDuktape_HECI_Session_EmitErrorEvent(void *chain, void *session)
{
if (ILibIsRunningOnChainThread(chain) == 0) { ILibChain_RunOnMicrostackThreadEx(chain, ILibDuktape_HECI_Session_EmitErrorEvent, session); }
if (ILibIsRunningOnChainThread(chain) == 0) { ILibChain_RunOnMicrostackThreadEx(chain, ILibDuktape_HECI_Session_EmitErrorEvent, session); return; }
ILibDuktape_HECI_Session *s = (ILibDuktape_HECI_Session*)session;
duk_context *ctx = s->stream->readableStream->ctx;
@@ -234,7 +250,7 @@ void ILibDuktape_HECI_Session_EmitErrorEvent(void *chain, void *session)
}
void ILibDuktape_HECI_Session_EmitStreamReady(void *chain, void *session)
{
if (ILibIsRunningOnChainThread(chain) == 0) { ILibChain_RunOnMicrostackThreadEx(chain, ILibDuktape_HECI_Session_EmitStreamReady, session); }
if (ILibIsRunningOnChainThread(chain) == 0) { ILibChain_RunOnMicrostackThreadEx(chain, ILibDuktape_HECI_Session_EmitStreamReady, session); return; }
ILibDuktape_DuplexStream_Ready(((ILibDuktape_HECI_Session*)session)->stream);
}
@@ -278,7 +294,7 @@ ILibTransport_DoneState ILibDuktape_HECI_Session_WriteHandler_Process(ILibDuktap
DWORD bytesWritten;
BOOL result = TRUE;
#else
size_t bytesWritten;
ssize_t bytesWritten;
#endif
while (ILibQueue_GetCount(session->PendingWrites) > 0)
@@ -662,6 +678,7 @@ duk_ret_t ILibDuktape_HECI_Session_connect(duk_context *ctx)
duk_ret_t ILibDuktape_HECI_create(duk_context *ctx)
{
duk_push_object(ctx); // [Session]
ILibDuktape_WriteID(ctx, "heci.session");
ILibDuktape_HECI_Push(ctx, NULL); // [Session][HECI]
duk_dup(ctx, -2); // [Session][HECI][Session]
duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Parent); // [Session][HECI]
@@ -939,7 +956,7 @@ void ILibDuktape_HECI_PostSelect(void* object, int slct, fd_set *readset, fd_set
}
if (FD_ISSET(h->descriptor, writeset))
{
printf("Writeset\n");
ILibDuktape_HECI_Session_WriteHandler_Process(h->session);
}
}
void ILibDuktape_HECI_Destroy(void *object)
@@ -957,6 +974,7 @@ void ILibDuktape_HECI_Destroy(void *object)
void ILibDuktape_HECI_Push(duk_context *ctx, void *chain)
{
duk_push_object(ctx); // [HECI]
ILibDuktape_WriteID(ctx, "heci");
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_HECI_Finalizer);
#ifdef WIN32

View File

@@ -1,3 +1,19 @@
/*
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef __DUKTAPEHECI__
#define __DUKTAPEHECI__

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006 - 2017 Intel Corporation
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -39,6 +39,14 @@ struct sockaddr_in6 duktape_internalAddress;
#define ILibDuktape_Memory_AllocTable "\xFF_MemoryAllocTable"
#define ILibDuktape_ObjectStashKey "\xFF_ObjectStashKey"
int ILibDuktape_GetReferenceCount(duk_context *ctx, duk_idx_t i)
{
int retVal = -1;
duk_inspect_value(ctx, i);
retVal = Duktape_GetIntPropertyValue(ctx, -1, "refc", -1);
duk_pop(ctx);
return(retVal-1);
}
void ILibDuktape_Push_ObjectStash(duk_context *ctx)
{
if (duk_has_prop_string(ctx, -1, ILibDuktape_ObjectStashKey))
@@ -299,7 +307,7 @@ void ILibDuktape_CreateEventWithSetterEx(duk_context *ctx, char *propName, duk_c
duk_push_string(ctx, propName); // [obj][prop]
duk_push_c_function(ctx, setterMethod, 1); // [obj][prop][setFunc]
duk_push_string(ctx, propName); // [obj][prop][setFunc][name]
duk_put_prop_string(ctx, -2, "name"); // [obj][prop][setFunc]
duk_put_prop_string(ctx, -2, "propName"); // [obj][prop][setFunc]
duk_def_prop(ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_SETTER); // [obj]
}
void ILibDuktape_CreateEventWithSetter(duk_context *ctx, char *propName, char *propNamePtr, void **hptr)
@@ -333,6 +341,7 @@ void ILibDuktape_Helper_AddHeapFinalizer(duk_context *ctx, ILibDuktape_HelperEve
duk_push_heap_stash(ctx); // [g]
duk_push_object(ctx); // [g][obj]
ILibDuktape_WriteID(ctx, "Mesh.ScriptContainer.heapFinalizer");
duk_push_pointer(ctx, user); // [g][obj][user]
duk_put_prop_string(ctx, -2, "user"); // [g][obj]
duk_push_pointer(ctx, handler); // [g][obj][handler]
@@ -362,19 +371,6 @@ int ILibDuktape_Process_GetExitCode(duk_context *ctx)
return(retVal);
}
ILibDuktape_EventEmitter *ILibDuktape_Process_GetEventEmitter(duk_context *ctx)
{
ILibDuktape_EventEmitter *retVal = NULL;
duk_push_global_object(ctx); // [g]
if (duk_has_prop_string(ctx, -1, "process"))
{
duk_get_prop_string(ctx, -1, "process"); // [g][process]
retVal = ILibDuktape_EventEmitter_GetEmitter_fromCurrent(ctx);
duk_pop(ctx); // [g]
}
duk_pop(ctx); // ...
return retVal;
}
void *ILibDuktape_GetProcessObject(duk_context *ctx)
{
@@ -420,7 +416,7 @@ void ILibDuktape_Process_UncaughtExceptionEx(duk_context *ctx, char *format, ...
void *j = ILibDuktape_GetProcessObject(ctx);
ILibDuktape_EventEmitter *emitter;
if (strcmp(errmsg, "Process.exit() forced script termination") == 0) { return; }
if (ILibString_IndexOf(errmsg, (int)errmsgLen, "Process.exit() forced script termination", 40) >= 0) { return; }
duk_push_heapptr(ctx, j); // [process]
emitter = ILibDuktape_EventEmitter_GetEmitter_fromCurrent(ctx);
@@ -454,7 +450,7 @@ void ILibDuktape_Process_UncaughtExceptionEx(duk_context *ctx, char *format, ...
duk_get_prop_string(emitter->ctx, -1, "emit"); // [process][emit]
duk_swap_top(emitter->ctx, -2); // [emit][this]
duk_push_string(emitter->ctx, "uncaughtException"); // [emit][this][eventName]
duk_push_error_object(emitter->ctx, DUK_ERR_UNCAUGHT_ERROR, "%s", dest);
duk_push_error_object(emitter->ctx, DUK_ERR_ERROR, "%s", dest);
duk_pcall_method(emitter->ctx, 2);
duk_pop(emitter->ctx); // ...
}
@@ -533,18 +529,11 @@ duk_ret_t ILibDuktape_IndependentFinalizer_Dispatch(duk_context *ctx)
handler(ctx, duk_get_heapptr(ctx, -1));
return 0;
}
void ILibDuktape_CreateIndependentFinalizer(duk_context *ctx, ILibDuktape_IndependentFinalizerHandler handler)
{
char tmp[255];
duk_push_object(ctx); // [obj]
duk_push_pointer(ctx, handler); // [obj][ptr]
duk_put_prop_string(ctx, -2, "ptr"); // [obj]
duk_dup(ctx, -2); // [obj][parent]
duk_put_prop_string(ctx, -2, "parent"); // [obj]
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_IndependentFinalizer_Dispatch);
sprintf_s(tmp, sizeof(tmp), "\xFF_%s", Duktape_GetStashKey(duk_get_heapptr(ctx, -1)));
duk_put_prop_string(ctx, -2, tmp);
void ILibDuktape_CreateFinalizer(duk_context *ctx, duk_c_function func)
{
ILibDuktape_EventEmitter_Create(ctx);
ILibDuktape_EventEmitter_PrependOnce(ctx, -1, "~", func);
}
duk_ret_t ILibDuktape_CreateProperty_InstanceMethod_Sink(duk_context *ctx)
{
@@ -630,10 +619,14 @@ 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)
duk_ret_t ILibDuktape_PointerValidation_Finalizer(duk_context *ctx)
{
duk_push_this(ctx);
void *chain = Duktape_GetChain(ctx);
void *obj = duk_get_heapptr(ctx, -1);
ILibDuktape_InValidatePointer(chain, obj);
duk_pop(ctx);
return(0);
}
void ILibDuktape_PointerValidation_Init(duk_context *ctx)
{
@@ -642,7 +635,7 @@ void ILibDuktape_PointerValidation_Init(duk_context *ctx)
{
// Not set up yet, so set it up
ILibDuktape_ValidatePointer(chain, duk_get_heapptr(ctx, -1));
ILibDuktape_CreateIndependentFinalizer(ctx, ILibDuktape_PointerValidation_Finalizer);
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_PointerValidation_Finalizer);
}
}
duk_ret_t ILibDuktape_Immediate_Sink(duk_context *ctx)
@@ -664,14 +657,17 @@ duk_ret_t ILibDuktape_Immediate_Sink(duk_context *ctx)
}
}
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); }
duk_push_heap_stash(ctx); // [stash]
duk_push_this(ctx); // [stash][immediate]
duk_del_prop_string(ctx, -2, Duktape_GetStashKey(duk_get_heapptr(ctx, -1)));
return(0);
}
void ILibDuktape_Immediate(duk_context *ctx, void ** args, int argsLen, ILibDuktape_ImmediateHandler callback)
void* ILibDuktape_Immediate(duk_context *ctx, void ** args, int argsLen, ILibDuktape_ImmediateHandler callback)
{
void *retval = NULL;
int i = 0;
duk_push_global_object(ctx); // [g]
duk_get_prop_string(ctx, -1, "setImmediate"); // [g][setImmediate]
@@ -690,13 +686,15 @@ void ILibDuktape_Immediate(duk_context *ctx, void ** args, int argsLen, ILibDukt
++i;
}
if (duk_pcall_method(ctx, 3) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "ILibDuktape_Immediate => immediate(): "); duk_pop(ctx); return; }
if (duk_pcall_method(ctx, 3) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "ILibDuktape_Immediate => immediate(): "); duk_pop(ctx); return(NULL); }
// [immediate]
retval = duk_get_heapptr(ctx, -1); // [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_put_prop_string(ctx, -2, Duktape_GetStashKey(retval)); // [stash]
duk_pop(ctx); // ...
return(retval);
}
void ILibDuktape_CreateInstanceMethodWithProperties(duk_context *ctx, char *funcName, duk_c_function funcImpl, duk_idx_t numArgs, unsigned int propertyCount, ...)
{

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006 - 2017 Intel Corporation
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -61,7 +61,6 @@ void ILibDuktape_Process_UncaughtExceptionEx(duk_context *ctx, char *format, ...
duk_ret_t ILibDuktape_Error(duk_context *ctx, char *format, ...);
typedef void(*ILibDuktape_IndependentFinalizerHandler)(duk_context *ctx, void *object);
void ILibDuktape_CreateIndependentFinalizer(duk_context *ctx, ILibDuktape_IndependentFinalizerHandler handler);
int ILibDuktape_Process_GetExitCode(duk_context *ctx);
void ILibDuktape_CreateEventWithGetter(duk_context *ctx, char *propName, duk_c_function getterMethod);
@@ -86,7 +85,7 @@ void ILibDuktape_CreateProperty_InstanceMethod(duk_context *ctx, char *methodNam
void ILibDuktape_CreateProperty_InstanceMethodEx(duk_context *ctx, char *methodName, void *funcHeapPtr);
void ILibDuktape_CreateReadonlyProperty(duk_context *ctx, char *propName);
#define ILibDuktape_CreateReadonlyProperty_int(ctx, propName, propValue) duk_push_int(ctx, propValue);ILibDuktape_CreateReadonlyProperty(ctx, propName)
#define ILibDuktape_CreateFinalizer(context, funcImpl) duk_push_c_function(context, funcImpl, 1); duk_set_finalizer(context, -2);
void ILibDuktape_CreateFinalizer(duk_context *ctx, duk_c_function func);
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);
@@ -102,7 +101,8 @@ int ILibDuktape_IsPointerValid(void *chain, void *ptr);
#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);
void* ILibDuktape_Immediate(duk_context *ctx, void ** args, int argsLen, ILibDuktape_ImmediateHandler callback);
int ILibDuktape_GetReferenceCount(duk_context *ctx, duk_idx_t i);
#define ILibDuktape_WriteID(ctx, id) duk_push_string(ctx, id);duk_put_prop_string(ctx, -2, ILibDuktape_OBJID)

View File

@@ -1,3 +1,19 @@
/*
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifdef WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
@@ -29,7 +45,7 @@ extern void ILibWebClient_ResetWCDO(struct ILibWebClientDataObject *wcdo);
#define ILibDuktape_CR2Agent "\xFF_CR2Agent"
#define ILibDuktape_CR2HTTPStream "\xFF_CR2HTTPStream"
#define ILibDuktape_CR2TLSStream "\xFF_CR2TLSStream"
#define ILibDuktape_CR2WS "\xFF_ClientRequest2WS"
#define ILibDuktape_CR2Transform "\xFF_CR2Transform"
#define ILibDuktape_FUNC "\xFF_FUNC"
#define IILibDuktape_HTTP_HoldingQueue "\xFF_HoldingQueue"
#define ILibDuktape_Http_Server_FixedBuffer "\xFF_Http_Server_FixedBuffer"
@@ -41,7 +57,9 @@ extern void ILibWebClient_ResetWCDO(struct ILibWebClientDataObject *wcdo);
#define ILibDuktape_HTTP2PipedWritable "\xFF_HTTP2PipedWritable"
#define ILibDuktape_HTTPStream2Data "\xFF_HTTPStream2Data"
#define ILibDuktape_HTTPStream2HTTP "\xFF_HTTPStream2HTTP"
#define ILibDuktape_HTTPStream2Socket "\xFF_HTTPStream2Socket"
#define ILibDuktape_IMSG2HttpStream "\xFF_IMSG2HttpStream"
#define ILibDuktape_IMSG2Ptr "\xFF_IMSG2Ptr"
#define ILibDuktape_IMSG2SR "\xFF_IMSG2ServerResponse"
#define ILibDuktape_NS2HttpServer "\xFF_Http_NetServer2HttpServer"
#define ILibDuktape_Options2ClientRequest "\xFF_Options2ClientRequest"
@@ -52,16 +70,17 @@ extern void ILibWebClient_ResetWCDO(struct ILibWebClientDataObject *wcdo);
#define ILibDuktape_Socket2CR "\xFF_Socket2CR"
#define ILibDuktape_Socket2HttpServer "\xFF_Socket2HttpServer"
#define ILibDuktape_Socket2HttpStream "\xFF_Socket2HttpStream"
#define ILibDuktape_Socket2DiedListener "\xFF_Socket2DiedListener"
#define ILibDuktape_Socket2TLS "\xFF_Socket2TLS"
#define ILibDuktape_SR2HttpStream "\xFF_ServerResponse2HttpStream"
#define ILibDuktape_SR2ImplicitHeaders "\xFF_ServerResponse2ImplicitHeaders"
#define ILibDuktape_SR2State "\xFF_ServerResponse2State"
#define ILibDuktape_SRUSER "\xFF_SRUSER"
#define ILibDuktape_SR2WS "\xFF_Http_ServerResponse2WS"
#define ILibDuktape_TLS2CR "\xFF_TLS2CR"
#define ILibDuktape_WebSocket_Client ((void*)0x01)
#define ILibDuktape_WebSocket_Server ((void*)0x02)
#define ILibDuktape_WebSocket_StatePtr "\xFF_WebSocketState"
#define ILibDuktape_WSENC2WS "\xFF_WSENC2WS"
#define ILibDuktape_WS2CR "\xFF_WS2ClientRequest"
#define ILibDuktape_WSDEC2WS "\xFF_WSDEC2WS"
@@ -73,6 +92,8 @@ typedef struct ILibDuktape_Http_ClientRequest_WriteData
int noMoreWrites;
int headersFinished;
int contentLengthSpecified;
int needRetry;
int retryCounter;
size_t bufferWriteLen;
size_t bufferLen;
}ILibDuktape_Http_ClientRequest_WriteData;
@@ -90,6 +111,7 @@ typedef struct ILibDuktape_HttpStream_Data
void *WCDO;
void *chain;
int ConnectMethod;
int endPropagated;
}ILibDuktape_HttpStream_Data;
typedef struct ILibDuktape_HttpStream_ServerResponse_State
@@ -129,6 +151,9 @@ typedef struct ILibDuktape_WebSocket_State
void *ObjectPtr; // Used to emit Ping/Pong events
duk_context *ctx; // Used to emit Ping/Pong events
int noResume;
int closed;
ILibDuktape_DuplexStream *encodedStream;
ILibDuktape_DuplexStream *decodedStream;
}ILibDuktape_WebSocket_State;
@@ -337,10 +362,10 @@ void ILibDuktape_HttpStream_http_ConvertOptionToSend(duk_context *ctx, void *Obj
while (duk_next(ctx, -1, 1))
{
tmp = (char*)duk_get_lstring(ctx, -2, &len);
if (buffer != NULL) { memcpy_s(buffer + bufferLen, ILibMemory_AllocateA_Size(buffer) - bufferLen, tmp, len); (buffer + bufferLen)[len] = ':'; }
if (buffer != NULL) { memcpy_s(buffer + bufferLen, ILibMemory_AllocateA_Size(buffer) - bufferLen, tmp, len); (buffer + bufferLen)[len] = ':'; (buffer + bufferLen)[len + 1] = ' '; }
if (len == 6 && strncasecmp(tmp, "expect", 6) == 0) { expectSpecified = 1; }
if (len == 14 && strncasecmp(tmp, "content-length", 14) == 0) { data->contentLengthSpecified = 1; }
bufferLen += (len + 1); // ('key:')
bufferLen += (len + 2); // ('key: ')
tmp = (char*)duk_get_lstring(ctx, -1, &len);
if (buffer != NULL) { memcpy_s(buffer + bufferLen, ILibMemory_AllocateA_Size(buffer) - bufferLen, tmp, len); (buffer + bufferLen)[len] = '\r'; (buffer + bufferLen)[len + 1] = '\n'; }
bufferLen += (len + 2); // ('value\r\n')
@@ -382,41 +407,21 @@ void ILibDuktape_HttpStream_http_ConvertOptionToSend(duk_context *ctx, void *Obj
duk_pop_n(ctx, 4); // ...
}
duk_ret_t ILibDuktape_HttpStream_http_OnTLSConnect(duk_context *ctx)
duk_ret_t ILibDuktape_HttpStream_http_WebSocket_closed(duk_context *ctx)
{
duk_push_this(ctx); // [TLS]
// ClientRequest Options => DecryptedTransform
duk_get_prop_string(ctx, -1, ILibDuktape_TLS2CR); // [TLS][ClientRequest]
duk_get_prop_string(ctx, -2, "clear"); // [TLS][ClientRequest][DecryptedTransform]
duk_get_prop_string(ctx, -2, ILibDuktape_CR2Options); // [TLS][ClientRequest][DecryptedTransform][Options]
ILibDuktape_HttpStream_http_ConvertOptionToSend(ctx, duk_get_heapptr(ctx, -2), duk_get_heapptr(ctx, -1));
// ClientRequest => DecryptedTransform
duk_pop(ctx); // [TLS][ClientRequest][DecryptedTransform]
duk_get_prop_string(ctx, -2, "pipe"); // [TLS][ClientRequest][DecryptedTransform][pipe]
duk_dup(ctx, -3); // [TLS][ClientRequest][DecryptedTransform][pipe][this]
duk_dup(ctx, -3); // [TLS][ClientRequest][DecryptedTransform][pipe][this][DecryptedTransform]
duk_push_object(ctx); // [TLS][ClientRequest][DecryptedTransform][pipe][this][DecryptedTransform][options]
duk_push_false(ctx); duk_put_prop_string(ctx, -2, "end");
if (duk_pcall_method(ctx, 2) != 0) { return(ILibDuktape_Error(ctx, "http.onTlsConnect() => Error calling pipe on Transform Stream: %s", duk_safe_to_string(ctx, -1))); }
duk_pop_2(ctx); // [TLS][ClientRequest]
// TLS EncryptedTransform => HTTP Stream
duk_get_prop_string(ctx, -2, "encrypted"); // [TLS][ClientRequest][EncryptedTransform]
duk_get_prop_string(ctx, -1, "pipe"); // [TLS][ClientRequest][EncryptedTransform][pipe]
duk_swap_top(ctx, -2); // [TLS][ClientRequest][pipe][this]
duk_get_prop_string(ctx, -3, ILibDuktape_CR2HTTPStream);// [TLS][ClientRequest][pipe][this][http]
if (duk_pcall_method(ctx, 1) != 0) { return(ILibDuktape_Error(ctx, "http.onTlsConnect() => Error calling pipe: %s", duk_safe_to_string(ctx, -1))); }
duk_pop(ctx); // [TLS][ClientRequest]
duk_get_prop_string(ctx, -1, ILibDuktape_CR2HTTPStream);// [TLS][ClientRequest][http]
duk_get_prop_string(ctx, -1, "pipe"); // [TLS][ClientRequest][http][pipe]
duk_swap_top(ctx, -2); // [TLS][ClientRequest][pipe][this]
duk_get_prop_string(ctx, -4, "clear"); // [TLS][ClientRequest][http][this][decryptedTransform]
if (duk_pcall_method(ctx, 1) != 0) { return(ILibDuktape_Error(ctx, "http.onTlsConnect() => Error calling pipe: %s", duk_safe_to_string(ctx, -1))); }
duk_push_this(ctx); // [socket]
if (duk_has_prop_string(ctx, -1, ILibDuktape_Socket2CR))
{
duk_get_prop_string(ctx, -1, ILibDuktape_Socket2CR); // [socket][CR]
duk_push_undefined(ctx); // [socket][CR][undefined]
ILibDuktape_CreateReadonlyProperty(ctx, "socket"); // [socket][CR]
duk_pop(ctx); // [socket]
duk_del_prop_string(ctx, -1, ILibDuktape_Socket2CR);
}
duk_get_prop_string(ctx, -1, "unpipe"); // [socket][unpipe]
duk_swap_top(ctx, -2); // [unpipe][this]
duk_call_method(ctx, 0);
return(0);
}
duk_ret_t ILibDuktape_HttpStream_http_onUpgrade(duk_context *ctx)
@@ -436,11 +441,27 @@ duk_ret_t ILibDuktape_HttpStream_http_onUpgrade(duk_context *ctx)
// We were upgraded to WebSocket, so we need to create a WebSocket Stream, detach the HTTPStream, and emit the event
// Upstream Readable => X => HttpStream
duk_push_this(ctx); // [HTTPStream]
if (duk_has_prop_string(ctx, -1, ILibDuktape_HTTP2CR))
{
duk_get_prop_string(ctx, -1, ILibDuktape_HTTP2CR); // [HTTPStream][CR]
duk_del_prop_string(ctx, -1, ILibDuktape_CR2HTTPStream);
duk_pop(ctx); // [HTTPStream]
}
duk_get_prop_string(ctx, -1, ILibDuktape_HTTP2PipedReadable); // [HTTPStream][readable]
if (duk_has_prop_string(ctx, -1, ILibDuktape_Socket2HttpStream))
{
duk_del_prop_string(ctx, -1, ILibDuktape_Socket2HttpStream);
}
duk_get_prop_string(ctx, -1, "unpipe"); // [HTTPStream][readable][unpipe]
duk_dup(ctx, -2); // [HTTPStream][readable][unpipe][this]
duk_call_method(ctx, 0); // [HTTPStream][readable][...]
duk_pop(ctx); // [HTTPStream][readable]
duk_get_prop_string(ctx, -1, "prependOnceListener"); // [HTTPStream][readable][prepend]
duk_dup(ctx, -2); // [HTTPStream][readable][prepend][this]
duk_push_string(ctx, "close"); // [HTTPStream][readable][prepend][this]['close']
duk_push_c_function(ctx, ILibDuktape_HttpStream_http_WebSocket_closed, DUK_VARARGS);
duk_call_method(ctx, 2); duk_pop(ctx); // [HTTPStream][readable]
duk_push_external_buffer(ctx); // [HTTPStream][readable][ext]
duk_config_buffer(ctx, -1, decodedKey, decodedKeyLen);
@@ -453,8 +474,8 @@ duk_ret_t ILibDuktape_HttpStream_http_onUpgrade(duk_context *ctx)
duk_remove(ctx, -2); // [HTTPStream][readable][websocket]
duk_get_prop_string(ctx, -3, ILibDuktape_HTTP2CR); // [HTTPStream][readable][websocket][clientRequest]
duk_dup(ctx, -2); // [HTTPStream][readable][websocket][clientRequest][websocket]
duk_put_prop_string(ctx, -2, ILibDuktape_CR2WS); // [HTTPStream][readable][websocket][clientRequest]
//duk_dup(ctx, -2); // [HTTPStream][readable][websocket][clientRequest][websocket]
//duk_put_prop_string(ctx, -2, ILibDuktape_CR2WS); // [HTTPStream][readable][websocket][clientRequest]
duk_put_prop_string(ctx, -2, ILibDuktape_WS2CR); // [HTTPStream][readable][websocket]
// Upstream Readable => WebSocket Encoded
@@ -475,9 +496,10 @@ duk_ret_t ILibDuktape_HttpStream_http_onUpgrade(duk_context *ctx)
duk_call_method(ctx, 1); // [HTTPStream][websocket][...]
duk_pop(ctx); // [HTTPStream][websocket]
}
duk_get_prop_string(ctx, -1, ILibDuktape_WS2CR); // [HTTPStream][websocket][clientRequest]
duk_get_prop_string(ctx, -1, "emit"); // [HTTPStream][websocket][clientRequest][emit]
duk_swap_top(ctx, -2); // [HTTPStream][websocket][emit][this]
duk_push_string(ctx, "upgrade"); // [HTTPStream][websocket][emit][this][upgrade]
duk_dup(ctx, 0); // [HTTPStream][websocket][emit][this][upgrade][imsg]
@@ -486,7 +508,7 @@ duk_ret_t ILibDuktape_HttpStream_http_onUpgrade(duk_context *ctx)
duk_remove(ctx, -2); // [HTTPStream][websocket][emit][this][upgrade][imsg][WS_DEC]
duk_push_null(ctx); // [HTTPStream][websocket][emit][this][upgrade][imsg][WS_DEC][null]
duk_call_method(ctx, 4); duk_pop(ctx); // [HTTPStream][websocket]
return(0);
}
duk_ret_t ILibDuktape_HttpStream_http_endResponseSink(duk_context *ctx)
@@ -494,21 +516,34 @@ duk_ret_t ILibDuktape_HttpStream_http_endResponseSink(duk_context *ctx)
duk_push_this(ctx); // [imsg]
duk_get_prop_string(ctx, -1, ILibDuktape_IMSG2HttpStream); // [imsg][httpstream]
duk_get_prop_string(ctx, -1, ILibDuktape_HTTP2CR); // [imsg][httpstream][CR]
duk_del_prop_string(ctx, -3, ILibDuktape_IMSG2HttpStream);
duk_del_prop_string(ctx, -2, ILibDuktape_HTTP2CR);
duk_del_prop_string(ctx, -1, ILibDuktape_CR2HTTPStream);
duk_get_prop_string(ctx, -1, "unpipe"); // [imsg][httpstream][CR][unpipe]
duk_dup(ctx, -2); // [imsg][httpstream][CR][unpipe][this]
duk_call_method(ctx, 0); duk_pop(ctx); // [imsg][httpstream][CR]
duk_get_prop_string(ctx, -1, "socket"); // [imsg][httpstream][CR][socket]
duk_insert(ctx, -4); // [socket][imsg][httpstream][CR]
duk_push_undefined(ctx); // [socket][imsg][httpstream][CR][undefined]
ILibDuktape_CreateReadonlyProperty(ctx, "socket"); // [socket][imsg][httpstream][CR]
if (Duktape_GetBooleanProperty(ctx, -2, "connectionCloseSpecified", 0) != 0)
{
// We cant persist this connection, so close the socket.
// Agent is already listening for the 'close' event, so it'll cleanup automatically
duk_get_prop_string(ctx, -1, "socket"); // [imsg][httpstream][CR][socket]
duk_get_prop_string(ctx, -1, "end"); // [imsg][httpstream][CR][socket][end]
duk_swap_top(ctx, -2); // [imsg][httpstream][CR][end][this]
duk_dup(ctx, -4); // [socket][imsg][httpstream][CR][socket]
duk_get_prop_string(ctx, -1, "end"); // [socket][imsg][httpstream][CR][socket][end]
duk_swap_top(ctx, -2); // [socket][imsg][httpstream][CR][end][this]
duk_call_method(ctx, 0);
return(0);
}
duk_get_prop_string(ctx, -1, ILibDuktape_CR2Agent); // [imsg][httpstream][CR][Agent]
duk_get_prop_string(ctx, -1, "keepSocketAlive"); // [imsg][httpstream][CR][Agent][keepSocketAlive]
duk_swap_top(ctx, -2); // [imsg][httpstream][CR][keepSocketAlive][this]
duk_get_prop_string(ctx, -3, "socket"); // [imsg][httpstream][CR][keepSocketAlive][this][socket]
duk_call_method(ctx, 1); duk_pop(ctx); // [imsg][httpstream][CR]
duk_get_prop_string(ctx, -1, ILibDuktape_CR2Agent); // [socket][imsg][httpstream][CR][Agent]
duk_get_prop_string(ctx, -1, "keepSocketAlive"); // [socket][imsg][httpstream][CR][Agent][keepSocketAlive]
duk_swap_top(ctx, -2); // [socket][imsg][httpstream][CR][keepSocketAlive][this]
duk_dup(ctx, -6); // [socket][imsg][httpstream][CR][keepSocketAlive][this][socket]
duk_call_method(ctx, 1); duk_pop(ctx); // [socket][imsg][httpstream][CR]
return(0);
}
duk_ret_t ILibDuktape_HttpStream_http_responseSink(duk_context *ctx)
@@ -517,8 +552,92 @@ duk_ret_t ILibDuktape_HttpStream_http_responseSink(duk_context *ctx)
duk_dup(ctx, 0); // [httpstream][imsg]
duk_swap_top(ctx, -2); // [imsg][httpstream]
duk_put_prop_string(ctx, -2, ILibDuktape_IMSG2HttpStream); // [imsg]
ILibDuktape_EventEmitter_AddOnceEx3(ctx, 0, "end", ILibDuktape_HttpStream_http_endResponseSink);
duk_pop(ctx);
return(0);
}
duk_ret_t ILibDuktape_HttpStream_http_SocketDiedPrematurely(duk_context *ctx)
{
duk_push_this(ctx); // [socket]
duk_get_prop_string(ctx, -1, ILibDuktape_Socket2CR); // [socket][clientRequest]
ILibDuktape_Transform *tf = (ILibDuktape_Transform*)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_CR2Transform);
if (tf->target->resumeImmediate != NULL)
{
duk_push_global_object(ctx); // [g]
duk_get_prop_string(ctx, -1, "clearImmediate"); // [g][clearImmediate]
duk_swap_top(ctx, -2); // [clearImmediate][this]
duk_push_heapptr(ctx, tf->target->resumeImmediate); // [clearImmediate][this][immedate]
duk_call_method(ctx, 1); duk_pop(ctx); // ...
tf->target->resumeImmediate = NULL;
}
duk_get_prop_string(ctx, -1, "unpipe"); // [socket][clientRequest][unpipe]
duk_dup(ctx, -2); // [socket][clientRequest][unpipe][this]
duk_call_method(ctx, 0); duk_pop(ctx); // [socket][clientRequest]
ILibDuktape_ReadableStream_DestroyPausedData(tf->target);
// Need to specify some stuff, so the request body will go out again
duk_get_prop_string(ctx, -1, ILibDuktape_CR_RequestBuffer); // [socket][clientRequest][buffer]
ILibDuktape_Http_ClientRequest_WriteData *wdata = (ILibDuktape_Http_ClientRequest_WriteData*)Duktape_GetBuffer(ctx, -1, NULL);
++wdata->retryCounter;
wdata->needRetry = 1;
wdata->bufferWriteLen = wdata->bufferLen;
wdata->headersFinished = 0;
duk_pop(ctx); // [socket][clientRequest]
if (wdata->retryCounter < 3)
{
duk_get_prop_string(ctx, -1, ILibDuktape_CR2Agent); // [socket][clientRequest][agent]
duk_get_prop_string(ctx, -1, "requests"); // [socket][clientReqeust][agent][requests]
duk_get_prop_string(ctx, -4, ILibDuktape_Socket2AgentKey); // [socket][clientRequest][agent][requests][key]
duk_get_prop(ctx, -2); // [socket][clientRequest][agent][requests][array]
if (!duk_is_undefined(ctx, -1))
{
// We need to prepend the clientRequest into the request Queue
duk_get_prop_string(ctx, -1, "unshift"); // [socket][clientRequest][agent][requests][array][unshift]
duk_swap_top(ctx, -2); // [socket][clientRequest][agent][requests][unshift][this]
duk_dup(ctx, -5); // [socket][clientRequest][agent][requests][unshift][this][clientRequest]
duk_call_method(ctx, 1);
}
}
else
{
ILibDuktape_EventEmitter_SetupEmit(ctx, duk_get_heapptr(ctx, -1), "error"); // [emit][this][error]
duk_push_error_object(ctx, DUK_ERR_ERROR, "Too many failed attempts"); // [emit][this][error][err]
duk_call_method(ctx, 2);
}
return(0);
}
duk_ret_t ILibDuktape_HttpStream_http_SocketResponseReceived(duk_context *ctx)
{
duk_push_this(ctx); // [httpStream]
duk_get_prop_string(ctx, -1, ILibDuktape_HTTPStream2Socket); // [httpStream][socket]
duk_get_prop_string(ctx, -1, ILibDuktape_Socket2CR); // [httpStream][socket][CR]
duk_get_prop_string(ctx, -1, ILibDuktape_CR2Options); // [httpStream][socket][CR][Options]
duk_del_prop_string(ctx, -1, ILibDuktape_Options2ClientRequest);
duk_pop_2(ctx); // [httpStream][socket]
duk_del_prop_string(ctx, -1, ILibDuktape_Socket2CR);
duk_get_prop_string(ctx, -1, "removeListener"); // [httpStream][socket][removeListener]
duk_swap_top(ctx, -2); // [httpStream][removeListener][this]
duk_push_string(ctx, "close"); // [httpStream][removeListener][this][close]
duk_get_prop_string(ctx, -2, ILibDuktape_Socket2DiedListener); // [httpStream][removeListener][this][close][listener]
duk_call_method(ctx, 2);
return(0);
}
duk_ret_t ILibDuktape_HttpStream_http_OnSocketClosed(duk_context *ctx)
{
duk_push_this(ctx); // [socket]
if (duk_has_prop_string(ctx, -1, ILibDuktape_Socket2HttpStream))
{
duk_get_prop_string(ctx, -1, ILibDuktape_Socket2HttpStream); // [socket][stream]
duk_pop(ctx); // [socket]
duk_del_prop_string(ctx, -1, ILibDuktape_Socket2HttpStream);
}
duk_pop(ctx); // ...
return(0);
}
duk_ret_t ILibDuktape_HttpStream_http_OnSocketReady(duk_context *ctx)
@@ -526,17 +645,54 @@ duk_ret_t ILibDuktape_HttpStream_http_OnSocketReady(duk_context *ctx)
void *httpStream;
duk_dup(ctx, 0); // [socket]
duk_push_c_function(ctx, ILibDuktape_HttpStream_http_SocketDiedPrematurely, DUK_VARARGS);
duk_put_prop_string(ctx, -2, ILibDuktape_Socket2DiedListener); // [socket]
duk_push_this(ctx); // [socket][clientRequest]
// Register ourselves for the close event, becuase we'll need to put ourselves back in the Queue if the socket dies before we are done
duk_get_prop_string(ctx, -2, "prependOnceListener"); // [socket][clientRequest][prependOnce]
duk_dup(ctx, -3); // [socket][clientRequest][prependOnce][this]
duk_push_string(ctx, "close"); // [socket][clientRequest][prependOnce][this][close]
duk_get_prop_string(ctx, -5, ILibDuktape_Socket2DiedListener); // [socket][clientRequest][prependOnce][this][close][listener]
duk_call_method(ctx, 2); duk_pop(ctx); // [socket][clientRequest]
duk_put_prop_string(ctx, -2, ILibDuktape_Socket2CR); // [socket]
duk_push_this(ctx); // [socket][clientRequest]
if (duk_has_prop_string(ctx, -2, ILibDuktape_Socket2HttpStream))
{
// HTTP and/or TLS was already setup previously
duk_get_prop_string(ctx, -2, ILibDuktape_Socket2HttpStream); // [socket][clientRequest][HTTPStream]
ILibDuktape_EventEmitter_AddOnceEx3(ctx, -1, "write", ILibDuktape_HttpStream_http_SocketResponseReceived);
duk_get_prop_string(ctx, -1, ILibDuktape_HTTPStream2Data); // [socket][clientRequest][HTTPStream][data]
ILibDuktape_HttpStream_Data *data = (ILibDuktape_HttpStream_Data*)Duktape_GetBuffer(ctx, -1, NULL);
ILibWebClient_ResetWCDO(data->WCDO);
if (data->bodyStream != NULL) { ILibDuktape_readableStream_WriteEnd(data->bodyStream); data->bodyStream = NULL; }
duk_pop(ctx); // [socket][clientRequest][HTTPStream]
// We need to change the events to propagate to the new clientRequest instead of the old one
duk_get_prop_string(ctx, -1, "removeAllListeners"); // [socket][clientRequest][HTTPStream][remove]
duk_dup(ctx, -2); // [socket][clientRequest][HTTPStream][remove][this]
duk_push_string(ctx, "response"); // [socket][clientRequest][HTTPStream][remove][this][response]
duk_call_method(ctx, 1); duk_pop(ctx); // [socket][clientRequest][HTTPStream]
duk_get_prop_string(ctx, -1, "removeAllListeners"); // [socket][clientRequest][HTTPStream][remove]
duk_dup(ctx, -2); // [socket][clientRequest][HTTPStream][remove][this]
duk_push_string(ctx, "continue"); // [socket][clientRequest][HTTPStream][remove][this][continue]
duk_call_method(ctx, 1); duk_pop(ctx); // [socket][clientRequest][HTTPStream]
duk_get_prop_string(ctx, -1, "removeAllListeners"); // [socket][clientRequest][HTTPStream][remove]
duk_dup(ctx, -2); // [socket][clientRequest][HTTPStream][remove][this]
duk_push_string(ctx, "upgrade"); // [socket][clientRequest][HTTPStream][remove][this][upgrade]
duk_call_method(ctx, 1); duk_pop(ctx); // [socket][clientRequest][HTTPStream]
duk_push_this(ctx); // [socket][clientRequest][HTTPStream][clientRequest]
duk_put_prop_string(ctx, -2, ILibDuktape_HTTP2CR); // [socket][clientRequest][HTTPStream]
ILibDuktape_EventEmitter_ForwardEvent(ctx, -1, "response", -2, "response");
ILibDuktape_EventEmitter_ForwardEvent(ctx, -1, "continue", -2, "continue");
ILibDuktape_EventEmitter_AddOnEx(ctx, -1, "upgrade", ILibDuktape_HttpStream_http_onUpgrade);
ILibDuktape_EventEmitter_AddOnEx(ctx, -1, "response", ILibDuktape_HttpStream_http_responseSink);
duk_get_prop_string(ctx, -1, ILibDuktape_HTTP2PipedWritable); // [socket][clientRequest][HTTPStream][destination]
duk_get_prop_string(ctx, -3, ILibDuktape_CR2Options); // [socket][clientRequest][HTTPStream][destination][Options]
ILibDuktape_HttpStream_http_ConvertOptionToSend(ctx, duk_get_heapptr(ctx, -2), duk_get_heapptr(ctx, -1));
@@ -573,13 +729,14 @@ duk_ret_t ILibDuktape_HttpStream_http_OnSocketReady(duk_context *ctx)
ILibDuktape_EventEmitter_ForwardEvent(ctx, -1, "continue", -2, "continue");
ILibDuktape_EventEmitter_AddOnEx(ctx, -1, "upgrade", ILibDuktape_HttpStream_http_onUpgrade);
ILibDuktape_EventEmitter_AddOnEx(ctx, -1, "response", ILibDuktape_HttpStream_http_responseSink);
ILibDuktape_EventEmitter_AddOnceEx3(ctx, -1, "write", ILibDuktape_HttpStream_http_SocketResponseReceived);
ILibDuktape_EventEmitter_AddOnceEx3(ctx, -3, "close", ILibDuktape_HttpStream_http_OnSocketClosed); // We need to detach HttpStream when socket closes
duk_put_prop_string(ctx, -2, ILibDuktape_CR2HTTPStream); // [socket][clientRequest]
duk_get_prop_string(ctx, -1, ILibDuktape_CR2Options); // [socket][clientRequest][options]
ILibDuktape_HttpStream_http_ConvertOptionToSend(ctx, duk_get_heapptr(ctx, -3), duk_get_heapptr(ctx, -1));
duk_pop(ctx); // [socket][clientRequest]
// ClientRequest => Socket
duk_get_prop_string(ctx, -1, "pipe"); // [socket][clientRequest][pipe]
duk_swap_top(ctx, -2); // [socket][pipe][this]
@@ -589,6 +746,12 @@ duk_ret_t ILibDuktape_HttpStream_http_OnSocketReady(duk_context *ctx)
if (duk_pcall_method(ctx, 2) != 0) { return(ILibDuktape_Error(ctx, "http.onConnect(): Error Piping with socket ")); }
duk_pop(ctx); // [socket]
// Save this value, so we can unregister 'close' from socket later
duk_push_heapptr(ctx, httpStream); // [socket][httpStream]
duk_dup(ctx, -2); // [socket][httpStream][socket]
duk_put_prop_string(ctx, -2, ILibDuktape_HTTPStream2Socket); // [socket][httpStream]
duk_pop(ctx); // [socket]
// Socket => HttpStream
duk_get_prop_string(ctx, -1, "pipe"); // [socket][pipe]
duk_dup(ctx, -2); // [socket][pipe][this]
@@ -601,8 +764,8 @@ duk_ret_t ILibDuktape_HttpStream_http_OnSocketReady(duk_context *ctx)
duk_get_prop_string(ctx, -1, "pipe"); // [socket][http][pipe]
duk_swap_top(ctx, -2); // [socket][pipe][this]
duk_dup(ctx, -3); // [socket][pipe][this][socket]
if (duk_pcall_method(ctx, 1) != 0) { return(ILibDuktape_Error(ctx, "http.onConnect(): Error calling pipe ")); }
if (duk_pcall_method(ctx, 1) != 0) { return(ILibDuktape_Error(ctx, "http.onConnect(): Error calling pipe ")); }
return(0);
}
duk_ret_t ILibDuktape_HttpStream_http_OnConnectError(duk_context *ctx)
@@ -708,37 +871,7 @@ duk_ret_t ILibDuktape_HttpStream_http_OnConnect(duk_context *ctx)
{
duk_ret_t retVal = 0;
duk_push_this(ctx); // [socket]
duk_get_prop_string(ctx, -1, ILibDuktape_SOCKET2OPTIONS); // [socket][options]
//if (duk_has_prop_string(ctx, -1, "proxy"))
//{
// duk_get_prop_string(ctx, -1, "proxy"); // [socket][options][proxy]
// duk_size_t remoteHostLen;
// char *remoteHost = (char*)Duktape_GetStringPropertyValueEx(ctx, -1, "remoteHost", NULL, &remoteHostLen);
// int remotePort = Duktape_GetIntPropertyValue(ctx, -1, "remotePort", 0);
// if (remoteHost != NULL && remotePort != 0)
// {
// duk_pop_2(ctx); // [socket]
// ILibDuktape_EventEmitter_AddOnEx(ctx, -1, "data", ILibDuktape_HttpStream_http_proxyData);
// duk_get_prop_string(ctx, -1, "write"); // [socket][write]
// duk_swap_top(ctx, -2); // [write][this]
// char *tmp = (char*)ILibMemory_AllocateA((2 * remoteHostLen) + 72);
// sprintf_s(tmp, ILibMemory_AllocateA_Size(tmp), "CONNECT %s:%u HTTP/1.1\r\nProxy-Connection: keep-alive\r\nHost: %s\r\n\r\n", remoteHost, remotePort, remoteHost);
// duk_push_string(ctx, tmp); // [write][this][chunk]
// duk_call_method(ctx, 1);
// return(0);
// }
// else
// {
// duk_pop(ctx); // [socket][options]
// }
//}
duk_pop(ctx); // [socket]
if (duk_has_prop_string(ctx, -1, ILibDuktape_Socket2CR))
{
// Socket was created with passed in createConnection
@@ -781,7 +914,7 @@ void ILibDuktape_HttpStream_http_request_transformPiped(struct ILibDuktape_Trans
ILibDuktape_readableStream_WriteData(sender->target, tmp, tmpLen);
if (data->bufferWriteLen > 0) { ILibDuktape_readableStream_WriteData(sender->target, data->buffer, (int)data->bufferWriteLen); }
}
else if(data->bufferWriteLen > 0)
else if(data->needRetry != 0)
{
if (data->headersFinished)
{
@@ -790,15 +923,27 @@ void ILibDuktape_HttpStream_http_request_transformPiped(struct ILibDuktape_Trans
else
{
data->headersFinished = 1;
tmpLen = sprintf_s(tmp, sizeof(tmp), "Transfer-Encoding: chunked\r\n\r\n%X\r\n", (unsigned int)data->bufferWriteLen);
if (data->contentLengthSpecified)
{
tmpLen = sprintf_s(tmp, sizeof(tmp), "Content-Length: %d\r\n\r\n", (int)data->bufferWriteLen);
}
else
{
tmpLen = sprintf_s(tmp, sizeof(tmp), "Transfer-Encoding: chunked\r\n\r\n%X\r\n", (unsigned int)data->bufferWriteLen);
}
}
ILibDuktape_readableStream_WriteData(sender->target, tmp, tmpLen);
ILibDuktape_readableStream_WriteData(sender->target, data->buffer, (int)data->bufferWriteLen);
ILibDuktape_readableStream_WriteData(sender->target, "\r\n", 2);
free(data->buffer);
data->buffer = NULL;
if (data->bufferWriteLen > 0)
{
ILibDuktape_readableStream_WriteData(sender->target, data->buffer, (int)data->bufferWriteLen);
if (!data->contentLengthSpecified) { ILibDuktape_readableStream_WriteData(sender->target, "\r\n", 2); }
free(data->buffer);
data->buffer = NULL;
}
data->bufferLen = data->bufferWriteLen = 0;
data->needRetry = 0;
}
}
void ILibDuktape_HttpStream_http_request_transform(struct ILibDuktape_Transform *sender, int Reserved, int flush, char *buffer, int bufferLen, void *user)
@@ -820,6 +965,13 @@ void ILibDuktape_HttpStream_http_request_transform(struct ILibDuktape_Transform
{
ILibDuktape_readableStream_WriteData(sender->target, buffer, bufferLen);
}
data->contentLengthSpecified = 1;
if (bufferLen > 0)
{
data->buffer = (char*)ILibMemory_Allocate(bufferLen, 0, NULL, NULL);
data->bufferLen = bufferLen;
memcpy_s(data->buffer, bufferLen, buffer, bufferLen);
}
}
else
{
@@ -844,11 +996,12 @@ void ILibDuktape_HttpStream_http_request_transform(struct ILibDuktape_Transform
}
}
duk_ret_t ILibDuktape_HttpStream_http_request(duk_context *ctx)
{
char *proto;
duk_size_t protoLen;
int isTLS = 0;
int nargs = duk_get_top(ctx);
if (duk_is_string(ctx, 0))
{
@@ -881,7 +1034,8 @@ duk_ret_t ILibDuktape_HttpStream_http_request(duk_context *ctx)
duk_put_prop_string(ctx, -2, "agent"); // [options][protocol][options]
duk_pop(ctx); // [options][protocol]
}
if ((protoLen == 4 && strncasecmp(proto, "wss:", 4) == 0) || (protoLen == 6 && strncasecmp(proto, "https:", 6) == 0)) { isTLS = 1; }
duk_pop(ctx); // [options]
if (!duk_has_prop_string(ctx, -1, "headers"))
{
@@ -912,15 +1066,16 @@ duk_ret_t ILibDuktape_HttpStream_http_request(duk_context *ctx)
duk_put_prop_string(ctx, -2, ILibDuktape_CR2HTTP); // [clientRequest]
duk_push_false(ctx);
duk_put_prop_string(ctx, -2, ILibDuktape_CR_EndCalled); // [clientRequest]
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_Http_ClientRequest_WriteData));
duk_put_prop_string(ctx, -2, ILibDuktape_CR_EndCalled); // [clientRequest]
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_Http_ClientRequest_WriteData)); // [clientRequest][buffer]
ILibDuktape_Http_ClientRequest_WriteData *wdata = (ILibDuktape_Http_ClientRequest_WriteData*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, ILibDuktape_CR_RequestBuffer);
duk_put_prop_string(ctx, -2, ILibDuktape_CR_RequestBuffer); // [clientRequest]
memset(wdata, 0, sizeof(ILibDuktape_Http_ClientRequest_WriteData));
ILibDuktape_Transform_Init(ctx, ILibDuktape_HttpStream_http_request_transform, ILibDuktape_HttpStream_http_request_transformPiped, wdata);
duk_push_pointer(ctx, ILibDuktape_Transform_Init(ctx, ILibDuktape_HttpStream_http_request_transform, ILibDuktape_HttpStream_http_request_transformPiped, wdata));
duk_put_prop_string(ctx, -2, ILibDuktape_CR2Transform); // [clientRequest]
ILibDuktape_WriteID(ctx, "https.clientRequest");
ILibDuktape_WriteID(ctx, isTLS ? "https.clientRequest" : "http.clientRequest");
ILibDuktape_EventEmitter *emitter = ILibDuktape_EventEmitter_Create(ctx);
ILibDuktape_EventEmitter_CreateEventEx(emitter, "abort");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "connect");
@@ -930,8 +1085,18 @@ duk_ret_t ILibDuktape_HttpStream_http_request(duk_context *ctx)
ILibDuktape_EventEmitter_CreateEventEx(emitter, "timeout");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "upgrade");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "error");
ILibDuktape_EventEmitter_AddOnEx(ctx, -1, "socket", ILibDuktape_HttpStream_http_OnSocketReady);
ILibDuktape_EventEmitter_AddOnceEx3(ctx, -1, "socket", ILibDuktape_HttpStream_http_OnSocketReady);
if (nargs > 1 && duk_is_function(ctx, 1))
{
duk_get_prop_string(ctx, -1, "once"); // [clientRequest][once]
duk_dup(ctx, -2); // [clientRequest][once][this]
duk_push_string(ctx, "response"); // [clientRequest][once][this][response]
duk_dup(ctx, 1); // [clientRequest][once][this][response][handler]
duk_call_method(ctx, 2); duk_pop(ctx); // [clientRequest]
}
duk_dup(ctx, 0); // [clientRequest][options]
duk_put_prop_string(ctx, -2, ILibDuktape_CR2Options); // [clientReqeust]
@@ -1185,7 +1350,6 @@ duk_ret_t ILibDuktape_HttpStream_http_server_upgradeWebsocket(duk_context *ctx)
duk_get_prop_string(ctx, -1, "webSocketStream"); // [http][constructor]
duk_push_lstring(ctx, keyResult, keyResultLen); // [http][constructor][key]
duk_new(ctx, 1); // [http][wss]
duk_push_this(ctx); // [http][wss][socket]
duk_get_prop_string(ctx, -1, "pipe"); // [http][wss][socket][pipe]
@@ -1311,7 +1475,8 @@ duk_ret_t ILibDuktape_HttpStream_http_server_onConnection(duk_context *ctx)
//ILibDuktape_EventEmitter_ForwardEvent(ctx, -2, "close", -1, "close");
ILibDuktape_EventEmitter_ForwardEvent(ctx, -2, "connect", -1, "connect");
ILibDuktape_EventEmitter_ForwardEvent(ctx, -2, "request", -1, "request");
ILibDuktape_EventEmitter_AddOnceEx3(ctx, -2, "upgrade", ILibDuktape_HttpStream_http_server_onUpgrade);
if (ILibDuktape_EventEmitter_HasListenersEx(ctx, -1, "upgrade") > 0) { ILibDuktape_EventEmitter_AddOnceEx3(ctx, -2, "upgrade", ILibDuktape_HttpStream_http_server_onUpgrade); }
duk_pop(ctx); // [NS][socket][pipe][this][httpStream]
duk_call_method(ctx, 1); duk_pop_2(ctx); // [NS]
@@ -1396,6 +1561,7 @@ duk_ret_t ILibDuktape_HttpStream_http_server_address(duk_context *ctx)
duk_call_method(ctx, 0); // [httpServer][result]
return(1);
}
duk_ret_t ILibDuktape_HttpStream_http_createServer(duk_context *ctx)
{
ILibDuktape_Http_Server *server;
@@ -1430,7 +1596,7 @@ duk_ret_t ILibDuktape_HttpStream_http_createServer(duk_context *ctx)
if (nargs > 0 && duk_is_function(ctx, 0))
{
ILibDuktape_EventEmitter_AddOn(emitter, "request", duk_require_heapptr(ctx, 1));
ILibDuktape_EventEmitter_AddOn(emitter, "request", duk_require_heapptr(ctx, 0));
}
ILibDuktape_CreateInstanceMethod(ctx, "close", ILibDuktape_HttpStream_http_server_close, DUK_VARARGS);
@@ -1451,18 +1617,17 @@ duk_ret_t ILibDuktape_HttpStream_http_createServer(duk_context *ctx)
duk_get_prop_string(ctx, -1, "createServer"); // [server][nettls][createServer]
duk_swap_top(ctx, -2); // [server][createServer][this]
if (nargs > 0 && duk_is_object(ctx, 0))
if (nargs > 0 && duk_is_object(ctx, 0) && !duk_is_function(ctx, 0))
{
// Options was specified
duk_dup(ctx, 0); // [server][createServer][this][options]
}
duk_push_c_function(ctx, ILibDuktape_HttpStream_http_server_onConnection, DUK_VARARGS);
duk_call_method(ctx, (nargs > 0 && duk_is_object(ctx, 0)) ? 2 : 1); // [server][netServer]
duk_call_method(ctx, (nargs > 0 && duk_is_object(ctx, 0) && !duk_is_function(ctx, 0)) ? 2 : 1); // [server][netServer]
duk_dup(ctx, -2); // [server][netServer][server]
duk_put_prop_string(ctx, -2, ILibDuktape_NS2HttpServer); // [server][netServer]
duk_put_prop_string(ctx, -2, ILibDuktape_Http_Server2NetServer); // [server]
return(1);
}
@@ -1547,6 +1712,13 @@ ILibTransport_DoneState ILibDuktape_HttpStream_WriteSink(ILibDuktape_DuplexStrea
return(ILibTransport_DoneState_INCOMPLETE);
}
duk_push_heapptr(DS->readableStream->ctx, DS->ParentObject); // [httpStream]
duk_get_prop_string(DS->readableStream->ctx, -1, "emit"); // [httpStream][emit]
duk_swap_top(DS->readableStream->ctx, -2); // [emit][this]
duk_push_string(DS->readableStream->ctx, "write"); // [emit][this][write]
if (duk_pcall_method(DS->readableStream->ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(DS->readableStream->ctx, "httpStream.write(): Error dispatching 'write' event "); }
duk_pop(DS->readableStream->ctx); // ...
// We're already on Chain Thread, so we can just directly write
int beginPointer = 0;
int PAUSE = 0;
@@ -1571,7 +1743,7 @@ ILibTransport_DoneState ILibDuktape_HttpStream_WriteSink(ILibDuktape_DuplexStrea
duk_swap_top(stream->ctx, -2); // [extBuffer][unshift][this]
duk_push_buffer_object(stream->ctx, -3, 0, (int)bufferLen - beginPointer, DUK_BUFOBJ_NODEJS_BUFFER);// [extBuffer][unshift][this][buffer]
if (duk_pcall_method(stream->ctx, 1) != 0) { MustBuffer = 1; }
duk_pop(stream->ctx); // ...
duk_pop_2(stream->ctx); // ...
}
else
{
@@ -1631,9 +1803,10 @@ void ILibDuktape_HttpStream_EndSink(ILibDuktape_DuplexStream *stream, void *user
{
ILibDuktape_HttpStream_Data *data = (ILibDuktape_HttpStream_Data*)user;
if (data->bodyStream != NULL)
if (data->bodyStream != NULL && data->endPropagated == 0)
{
ILibDuktape_readableStream_WriteEnd(data->bodyStream);
data->endPropagated = 1;
}
}
void ILibDuktape_HttpStream_ServerResponse_WriteImplicitHeaders(void *chain, void *user)
@@ -1786,9 +1959,9 @@ ILibTransport_DoneState ILibDuktape_HttpStream_ServerResponse_WriteSink(struct I
tmp->writeStream = state->writeStream;
tmp->endBytes = stream->endBytes;
tmp->chunk = state->chunkSupported;
if (bufferLen > 0) { memcpy_s(tmp->buffer, bufferLen, buffer, bufferLen); }
if (bufferLen > 0) { memcpy_s(tmp->buffer, bufferLen, buffer, bufferLen); tmp->bufferLen = bufferLen; }
ILibDuktape_HttpStream_ServerResponse_WriteImplicitHeaders(NULL, &tmp);
ILibDuktape_HttpStream_ServerResponse_WriteImplicitHeaders(NULL, tmp);
return(ILibTransport_DoneState_COMPLETE);
}
else
@@ -2216,9 +2389,21 @@ void ILibDuktape_HttpStream_ServerResponse_PUSH(duk_context *ctx, void* writeStr
{
ILibDuktape_HttpStream_ServerResponse_State *state;
duk_push_object(ctx); // [resp]
duk_push_heapptr(ctx, httpStream); // [resp][httpStream]
duk_put_prop_string(ctx, -2, ILibDuktape_SR2HttpStream); // [resp]
duk_push_object(ctx); // [resp]
duk_push_heapptr(ctx, httpStream); // [resp][httpStream]
duk_dup(ctx, -1); // [resp][httpStream][dup]
duk_put_prop_string(ctx, -3, ILibDuktape_SR2HttpStream); // [resp][httpStream]
duk_get_prop_string(ctx, -1, ILibDuktape_HTTPStream2HTTP); // [resp][httpStream][http]
duk_get_prop_string(ctx, -1, ILibDuktape_OBJID); // [resp][httpStream][http][id]
duk_remove(ctx, -2); // [resp][httpStream][id]
duk_get_prop_string(ctx, -1, "concat"); // [resp][httpStream][id][concat]
duk_swap_top(ctx, -2); // [resp][httpStream][concat][this]
duk_push_string(ctx, ".serverResponse"); // [resp][httpStream][concat][this][serverResponse]
if (duk_pcall_method(ctx, 1) != 0) { duk_pop(ctx); duk_push_string(ctx, "http[s].serverResponse"); } // [resp][httpStream][http/s.serverResponse]
duk_remove(ctx, -2); // [resp][http/s.serverResponse]
duk_put_prop_string(ctx, -2, ILibDuktape_OBJID); // [resp]
ILibDuktape_PointerValidation_Init(ctx);
ILibDuktape_WriteID(ctx, "http.serverResponse");
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_HttpStream_ServerResponse_State)); // [resp][state]
@@ -2408,11 +2593,27 @@ duk_ret_t ILibDuktape_HttpStream_IncomingMessage_Digest_ValidatePassword(duk_con
duk_push_int(ctx, retVal);
return(1);
}
duk_ret_t ILibDuktape_HttpStream_IncomingMessage_finalizer(duk_context *ctx)
{
return(0);
}
void ILibDuktape_HttpStream_IncomingMessage_PUSH(duk_context *ctx, ILibHTTPPacket *header, void *httpstream)
{
duk_push_object(ctx); // [message]
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_HttpStream_IncomingMessage_finalizer);
duk_push_heapptr(ctx, httpstream); // [message][httpStream]
duk_put_prop_string(ctx, -2, ILibDuktape_IMSG2HttpStream); // [message]
duk_dup(ctx, -1); // [message][httpStream][dup]
duk_put_prop_string(ctx, -3, ILibDuktape_IMSG2HttpStream); // [message][httpStream]
duk_get_prop_string(ctx, -1, ILibDuktape_HTTPStream2HTTP); // [message][httpStream][http]
duk_remove(ctx, -2); // [message][http]
duk_get_prop_string(ctx, -1, ILibDuktape_OBJID); // [message][http][id]
duk_get_prop_string(ctx, -1, "concat"); // [message][http][id][concat]
duk_swap_top(ctx, -2); // [message][http][concat][this]
duk_push_string(ctx, ".IncomingMessage"); // [message][http][concat][this][.IncomingMessage]
if (duk_pcall_method(ctx, 1) != 0) { duk_pop(ctx); duk_push_string(ctx, "http[s].IncomingMessage"); }
duk_remove(ctx, -2); // [message][http/s.IncomingMessage]
duk_put_prop_string(ctx, -2, ILibDuktape_OBJID); // [message]
duk_push_object(ctx); // [message][headers]
packetheader_field_node *node = header->FirstField;
while (node != NULL)
@@ -2479,7 +2680,26 @@ void ILibDuktape_HttpStream_DispatchEnd(void *chain, void *user)
}
free(user);
}
void ILibDuktape_HttpStream_ForceDisconnect(duk_context *ctx, void ** args, int argsLen)
{
duk_push_heapptr(ctx, args[0]);
duk_get_prop_string(ctx, -1, "end");
duk_swap_top(ctx, -2);
if (duk_pcall_method(ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "httpStream.OnUpgrade(): "); }
duk_pop(ctx);
}
duk_ret_t ILibDuktape_HttpStream_OnReceive_bodyStreamFinalized(duk_context *ctx)
{
ILibDuktape_HttpStream_Data *data = (ILibDuktape_HttpStream_Data*)Duktape_GetPointerProperty(ctx, 0, ILibDuktape_IMSG2Ptr);
if (data != NULL)
{
if (data->endPropagated == 0) { ILibDuktape_readableStream_WriteEnd(data->bodyStream); }
data->endPropagated = 1;
data->bodyStream = NULL;
}
return(0);
}
void ILibDuktape_HttpStream_OnReceive(ILibWebClient_StateObject WebStateObject, int InterruptFlag, struct packetheader *header, char *bodyBuffer, int *beginPointer, int endPointer, ILibWebClient_ReceiveStatus recvStatus, void *user1, void *user2, int *PAUSE)
{
ILibDuktape_HttpStream_Data *data = (ILibDuktape_HttpStream_Data*)user1;
@@ -2525,7 +2745,22 @@ void ILibDuktape_HttpStream_OnReceive(ILibWebClient_StateObject WebStateObject,
ILibDuktape_HttpStream_IncomingMessage_PUSH(ctx, header, data->DS->ParentObject); // [emit][this][upgrade][imsg]
ILibDuktape_HttpStream_ServerResponse_PUSH(ctx, data->DS->writableStream->pipedReadable, header, data->DS->ParentObject); // [emit][this][request][imsg][rsp]
duk_put_prop_string(ctx, -2, ILibDuktape_IMSG2SR);
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "http.httpStream.onReceive->upgrade(): "); }
if (duk_pcall_method(ctx, 2) != 0)
{ ILibDuktape_Process_UncaughtExceptionEx(ctx, "http.httpStream.onReceive->upgrade(): "); }
else
{
if (!duk_get_boolean(ctx, -1))
{
// No upgrade listener... Close connection
printf("\n\nNo Upgrade Listener\n");
void *imm = ILibDuktape_Immediate(ctx, (void*[]) { data->DS->writableStream->pipedReadable }, 1, ILibDuktape_HttpStream_ForceDisconnect);
duk_push_heapptr(ctx, imm);
duk_push_heapptr(ctx, data->DS->writableStream->pipedReadable);
duk_put_prop_string(ctx, -2, "r");
duk_pop_2(ctx);
return;
}
}
duk_pop(ctx); // ...
}
else
@@ -2604,15 +2839,27 @@ void ILibDuktape_HttpStream_OnReceive(ILibWebClient_StateObject WebStateObject,
case 101:
duk_push_string(ctx, "upgrade"); // [emit][this][upgrade]
ILibDuktape_HttpStream_IncomingMessage_PUSH(ctx, header, data->DS->ParentObject); // [emit][this][upgrade][imsg]
duk_del_prop_string(ctx, -1, ILibDuktape_IMSG2HttpStream);
duk_insert(ctx, -4); // [imsg][emit][this][upgrade]
duk_dup(ctx, -4); // [imsg][emit][this][upgrade][imsg]
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "http.httpStream.onReceive->upgrade(): "); }
duk_pop(ctx);
duk_pop(ctx);
break;
default:
duk_push_string(ctx, "response"); // [emit][this][response]
ILibDuktape_HttpStream_IncomingMessage_PUSH(ctx, header, data->DS->ParentObject); // [emit][this][response][imsg]
data->bodyStream = ILibDuktape_ReadableStream_InitEx(ctx, ILibDuktape_HttpStream_IncomingMessage_PauseSink, ILibDuktape_HttpStream_IncomingMessage_ResumeSink, ILibDuktape_HttpStream_IncomingMessage_UnshiftBytes, data);
duk_push_pointer(ctx, data);
duk_put_prop_string(ctx, -2, ILibDuktape_IMSG2Ptr);
ILibDuktape_EventEmitter_AddOnEx(ctx, -1, "~", ILibDuktape_HttpStream_OnReceive_bodyStreamFinalized);
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "http.httpStream.onReceive->response(): "); }
duk_pop(ctx);
if (bodyBuffer != NULL && endPointer > 0)
{
ILibDuktape_readableStream_WriteData(data->bodyStream, bodyBuffer + *beginPointer, endPointer);
}
break;
}
}
@@ -2620,6 +2867,7 @@ void ILibDuktape_HttpStream_OnReceive(ILibWebClient_StateObject WebStateObject,
if (data->bodyStream != NULL && recvStatus == ILibWebClient_ReceiveStatus_Complete)
{
ILibDuktape_readableStream_WriteEnd(data->bodyStream);
data->endPropagated = 1;
}
if (recvStatus == ILibWebClient_ReceiveStatus_Complete)
{
@@ -2651,7 +2899,6 @@ duk_ret_t ILibDuktape_HttpStream_Finalizer(duk_context *ctx)
ILibDuktape_InValidateHeapPointer(ctx, 0);
ILibWebClient_DestroyWebClientDataObject(data->WCDO);
return(0);
}
@@ -2702,6 +2949,7 @@ duk_ret_t ILibduktape_HttpStream_create(duk_context *ctx)
ILibDuktape_EventEmitter_CreateEventEx(emitter, "clientError");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "request");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "connect");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "write");
data->DS = ILibDuktape_DuplexStream_InitEx(ctx, ILibDuktape_HttpStream_WriteSink, ILibDuktape_HttpStream_EndSink,
NULL, NULL, NULL, data);
@@ -2772,7 +3020,7 @@ void ILibDuktape_RemoveObjFromTable(duk_context *ctx, duk_idx_t tableIdx, char *
duk_ret_t ILibDuktape_HttpStream_Agent_socketEndSink(duk_context *ctx)
{
duk_push_this(ctx); // [socket]
printf("socket has closed: %p\n", duk_get_heapptr(ctx, -1));
//printf("socket has closed: %p\n", duk_get_heapptr(ctx, -1));
duk_get_prop_string(ctx, -1, ILibDuktape_Socket2Agent); // [socket][agent]
duk_get_prop_string(ctx, -2, ILibDuktape_Socket2AgentKey); // [socket][agent][key]
char *key = Duktape_GetBuffer(ctx, -1, NULL);
@@ -2806,10 +3054,10 @@ duk_ret_t ILibDuktape_HttpStream_Agent_socketEndSink(duk_context *ctx)
duk_get_prop_string(ctx, -1, "createConnection"); // [socket][agent][agent][createConnection]
duk_swap_top(ctx, -2); // [socket][agent][createConnection][this]
duk_get_prop_string(ctx, -4, "\xFF_NET_SOCKET2OPTIONS"); // [socket][agent][createConnection][this][options]
duk_call_method(ctx, 1); // [socket][agent][newsocket]
duk_push_c_function(ctx, ILibDuktape_HttpStream_http_OnConnect, DUK_VARARGS); // We need to register here, because TLS/NonTLS have different event names
duk_call_method(ctx, 2); // [socket][agent][newsocket]
duk_swap_top(ctx, -2); // [socket][newsocket][agent]
duk_put_prop_string(ctx, -2, ILibDuktape_Socket2Agent); // [socket][newsocket]
ILibDuktape_EventEmitter_AddOnceEx3(ctx, -1, "connect", ILibDuktape_HttpStream_http_OnConnect);
ILibDuktape_EventEmitter_AddOnceEx3(ctx, -1, "error", ILibDuktape_HttpStream_http_OnConnectError);
}
}
@@ -2882,6 +3130,7 @@ duk_ret_t ILibDuktape_HttpStream_Agent_keepSocketAlive(duk_context *ctx)
duk_dup(ctx, -4); // [key][Agent][requests][request][reuseSocket][this][socket][request]
duk_call_method(ctx, 2); // [key][Agent][requests][request][retVal]
retVal = 1;
duk_pop(ctx); // [key][Agent][requests][request]
}
}
if (retVal == 0)
@@ -2917,6 +3166,11 @@ duk_ret_t ILibDuktape_HttpStream_Agent_keepSocketAlive(duk_context *ctx)
}
void ILibDuktape_HttpStream_Agent_reuseSocketEx(duk_context *ctx, void ** args, int argsLen)
{
duk_push_this(ctx); // [immediate]
duk_del_prop_string(ctx, -1, "CR");
duk_del_prop_string(ctx, -2, "Socket");
duk_pop(ctx); // ...
duk_push_heapptr(ctx, args[1]); // [clientRequest]
duk_push_heapptr(ctx, args[0]); // [clientRequest][socket]
@@ -2926,6 +3180,7 @@ void ILibDuktape_HttpStream_Agent_reuseSocketEx(duk_context *ctx, void ** args,
duk_call_method(ctx, 1); duk_pop(ctx); // [clientRequest][socket]
ILibDuktape_CreateReadonlyProperty(ctx, "socket"); // [clientRequest]
duk_get_prop_string(ctx, -1, "emit"); // [clientRequest][emit]
duk_swap_top(ctx, -2); // [emit][this]
duk_push_string(ctx, "socket"); // [emit][this][name]
@@ -2936,7 +3191,13 @@ void ILibDuktape_HttpStream_Agent_reuseSocketEx(duk_context *ctx, void ** args,
duk_ret_t ILibDuktape_HttpStream_Agent_reuseSocket(duk_context *ctx)
{
// Yield to the next loop, before we emit a 'socket' event, because emitting this event before anyone has the clientRequest object is pointless
ILibDuktape_Immediate(ctx, (void*[]) { duk_get_heapptr(ctx, 0), duk_get_heapptr(ctx, 1) }, 2, ILibDuktape_HttpStream_Agent_reuseSocketEx);
void *imm = ILibDuktape_Immediate(ctx, (void*[]) { duk_get_heapptr(ctx, 0), duk_get_heapptr(ctx, 1) }, 2, ILibDuktape_HttpStream_Agent_reuseSocketEx);
duk_push_heapptr(ctx, imm); // [immediate]
duk_dup(ctx, 1); // [immediate][ClientRequest]
duk_put_prop_string(ctx, -2, "CR"); // [immediate]
duk_dup(ctx, 0); // [immediate][Socket]
duk_put_prop_string(ctx, -2, "Socket"); // [immediate]
duk_pop(ctx);
return(0);
}
duk_ret_t ILibDuktape_HttpStream_Agent_createConnection_eventSink(duk_context *ctx)
@@ -3144,8 +3405,15 @@ ILibTransport_DoneState ILibDuktape_httpStream_webSocket_WriteWebSocketPacket(IL
if (ILibIsRunningOnChainThread(state->chain) != 0)
{
// We're on the Duktape Thread, so we can just call write multiple times, cuz we won't interleave with JavaScript
ILibDuktape_DuplexStream_WriteData(state->encodedStream, header, headerLen);
retVal = ILibDuktape_DuplexStream_WriteData(state->encodedStream, buffer, bufferLen) == 0 ? ILibTransport_DoneState_COMPLETE : ILibTransport_DoneState_INCOMPLETE;
if (bufferLen > 0)
{
ILibDuktape_DuplexStream_WriteData(state->encodedStream, header, headerLen);
retVal = ILibDuktape_DuplexStream_WriteData(state->encodedStream, buffer, bufferLen) == 0 ? ILibTransport_DoneState_COMPLETE : ILibTransport_DoneState_INCOMPLETE;
}
else
{
retVal = ILibDuktape_DuplexStream_WriteData(state->encodedStream, header, headerLen) == 0 ? ILibTransport_DoneState_COMPLETE : ILibTransport_DoneState_INCOMPLETE;
}
}
else
{
@@ -3314,6 +3582,7 @@ ILibTransport_DoneState ILibDuktape_httpStream_webSocket_EncodedWriteSink(ILibDu
switch (OPCODE)
{
case WEBSOCKET_OPCODE_CLOSE:
state->closed = 1;
ILibDuktape_DuplexStream_WriteEnd(state->decodedStream);
if (ILibIsRunningOnChainThread(state->chain) != 0 && state->encodedStream->writableStream->pipedReadable != NULL)
{
@@ -3363,7 +3632,7 @@ ILibTransport_DoneState ILibDuktape_httpStream_webSocket_EncodedWriteSink(ILibDu
void ILibDuktape_httpStream_webSocket_EncodedEndSink(ILibDuktape_DuplexStream *stream, void *user)
{
ILibDuktape_WebSocket_State *state = (ILibDuktape_WebSocket_State*)user;
ILibDuktape_DuplexStream_WriteEnd(state->decodedStream);
if (!state->closed) { ILibDuktape_DuplexStream_WriteEnd(state->decodedStream); }
}
void ILibDuktape_httpStream_webSocket_EncodedPauseSink_Chain(void *chain, void *user)
{
@@ -3453,6 +3722,14 @@ void ILibDuktape_httpStream_webSocket_DecodedPauseSink_Chain(void *chain, void *
ILibDuktape_WebSocket_State *state = (ILibDuktape_WebSocket_State*)user;
duk_context *ctx = state->encodedStream->writableStream->ctx;
if (state->encodedStream->writableStream->pipedReadable == NULL)
{
// We're not piped yet, so just set a flag, and we'll make sure we don't resume
state->noResume = 1;
return;
}
duk_push_heapptr(ctx, state->encodedStream->writableStream->pipedReadable); // [readable]
duk_get_prop_string(ctx, -1, "pause"); // [readable][pause]
duk_swap_top(ctx, -2); // [pause][this]
@@ -3485,6 +3762,12 @@ void ILibDuktape_httpStream_webSocket_DecodedResumeSink_Chain(void *chain, void
ILibDuktape_WebSocket_State *state = (ILibDuktape_WebSocket_State*)user;
duk_context *ctx = state->encodedStream->writableStream->ctx;
if (state->encodedStream->writableStream->pipedReadable == NULL)
{
state->noResume = 0;
return;
}
duk_push_heapptr(ctx, state->encodedStream->writableStream->pipedReadable); // [readable]
duk_get_prop_string(ctx, -1, "resume"); // [readable][resume]
duk_swap_top(ctx, -2); // [resume][this]
@@ -3521,6 +3804,17 @@ duk_ret_t ILibDuktape_httpStream_webSocketStream_finalizer(duk_context *ctx)
{
void *chain = Duktape_GetChain(ctx);
duk_get_prop_string(ctx, 0, ILibDuktape_WebSocket_StatePtr);
ILibDuktape_WebSocket_State *state = (ILibDuktape_WebSocket_State*)Duktape_GetBuffer(ctx, -1, NULL);
if (state->encodedStream->writableStream->pipedReadable != NULL)
{
duk_push_heapptr(ctx, state->encodedStream->writableStream->pipedReadable); // [readable]
duk_get_prop_string(ctx, -1, "unpipe"); // [readable][unpipe]
duk_swap_top(ctx, -2); // [unpipe][this]
duk_push_heapptr(ctx, state->encodedStream->writableStream->obj); // [unpipe][this][ws]
duk_call_method(ctx, 1); duk_pop(ctx); // ...
}
ILibDuktape_InValidatePointer(chain, Duktape_GetBuffer(ctx, -1, NULL));
return(0);
}
@@ -3544,6 +3838,24 @@ duk_ret_t ILibDuktape_httpStream_webSocketStream_sendPong(duk_context *ctx)
ILibDuktape_httpStream_webSocket_WriteWebSocketPacket(state, WEBSOCKET_OPCODE_PONG, NULL, 0, ILibWebClient_WebSocket_FragmentFlag_Complete);
return(0);
}
duk_ret_t ILibDuktape_httpStream_webSocketStream_encodedPiped(duk_context *ctx)
{
// Someone Piped to the Encoded Stream
duk_push_this(ctx); // [ENC]
duk_get_prop_string(ctx, -1, ILibDuktape_WSENC2WS); // [ENC][WS]
duk_get_prop_string(ctx, -1, ILibDuktape_WebSocket_StatePtr); // [ENC][WS][state]
ILibDuktape_WebSocket_State *state = (ILibDuktape_WebSocket_State*)Duktape_GetBuffer(ctx, -1, NULL);
if (state->noResume)
{
state->noResume = 0;
duk_push_heapptr(state->ctx, state->encodedStream->writableStream->pipedReadable); // [Readable]
duk_get_prop_string(state->ctx, -1, "pause"); // [Readable][pause]
duk_swap_top(ctx, -2); // [pause][this]
duk_call_method(ctx, 0);
}
return(0);
}
duk_ret_t ILibDuktape_httpStream_webSocketStream_new(duk_context *ctx)
{
@@ -3562,6 +3874,10 @@ duk_ret_t ILibDuktape_httpStream_webSocketStream_new(duk_context *ctx)
duk_push_object(ctx); // [WebSocket][Encoded]
ILibDuktape_WriteID(ctx, "http.WebSocketStream.encoded");
state->encodedStream = ILibDuktape_DuplexStream_InitEx(ctx, ILibDuktape_httpStream_webSocket_EncodedWriteSink, ILibDuktape_httpStream_webSocket_EncodedEndSink, ILibDuktape_httpStream_webSocket_EncodedPauseSink, ILibDuktape_httpStream_webSocket_EncodedResumeSink, ILibDuktape_httpStream_webSocket_EncodedUnshiftSink, state);
ILibDuktape_EventEmitter_AddOnEx(ctx, -1, "pipe", ILibDuktape_httpStream_webSocketStream_encodedPiped);
duk_dup(ctx, -2); // [WebSocket][Encoded][WebSocket]
duk_put_prop_string(ctx, -2, ILibDuktape_WSENC2WS); // [WebSocket][Encoded]
ILibDuktape_CreateReadonlyProperty(ctx, "encoded"); // [WebSocket]
duk_push_object(ctx); // [WebSocket][Decoded]
ILibDuktape_WriteID(ctx, "http.WebSocketStream.decoded");

View File

@@ -1,3 +1,19 @@
/*
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "duktape.h"
#include "ILibDuktapeModSearch.h"
#include "ILibDuktape_Helpers.h"

View File

@@ -1,3 +1,18 @@
/*
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "duktape.h"
#include "ILibDuktapeModSearch.h"
@@ -15,9 +30,6 @@ typedef struct ILibDuktape_NetworkMonitor
ILibDuktape_EventEmitter *emitter;
ILibIPAddressMonitor addressMonitor;
ILibHashtable *addressTable;
void *OnChange;
void *OnAdded;
void *OnRemoved;
}ILibDuktape_NetworkMonitor;
@@ -63,45 +75,31 @@ ILibHashtable ILibDuktape_NetworkMonitor_CreateTable(duk_context *ctx)
void ILibDuktape_NetworkMonitor_EventSink_OnEnumerateCurrent(ILibHashtable sender, void *Key1, char* Key2, int Key2Len, void *Data, void *user)
{
duk_context *ctx = (duk_context*)((void**)user)[0];
void *OnEvent = ((void**)user)[1];
char *eventName = (char*)((void**)user)[1];
void *Self = ((void**)user)[2];
ILibHashtable other = (ILibHashtable)((void**)user)[3];
if (ILibHashtable_Get(other, NULL, Key2, Key2Len) == NULL)
{
if (OnEvent != NULL)
{
duk_push_heapptr(ctx, OnEvent); // [func]
duk_push_heapptr(ctx, Self); // [func][this]
duk_push_lstring(ctx, Key2, (duk_size_t)Key2Len); // [func][this][address]
if (duk_pcall_method(ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "NetworkMonitor.OnAdd/Remove(): "); }
duk_pop(ctx);
}
ILibDuktape_EventEmitter_SetupEmit(ctx, Self, eventName); // [emit][this][eventName]
duk_push_lstring(ctx, Key2, (duk_size_t)Key2Len); // [emit][this][eventName][address]
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "NetworkMonitor.OnAdd/Remove(): "); }
duk_pop(ctx);
}
}
void ILibDuktape_NetworkMonitor_EventSink(ILibIPAddressMonitor sender, void *user)
{
ILibDuktape_NetworkMonitor *nm = (ILibDuktape_NetworkMonitor*)user;
if (nm->OnChange != NULL)
{
duk_push_heapptr(nm->ctx, nm->OnChange); // [func]
duk_push_heapptr(nm->ctx, nm->emitter->object); // [func][this]
if (duk_pcall_method(nm->ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(nm->ctx, "NetworkMonitor.change(): "); }
duk_pop(nm->ctx); // ...
}
ILibDuktape_EventEmitter_SetupEmit(nm->ctx, nm->emitter->object, "change"); // [emit][this][change]
if (duk_pcall_method(nm->ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(nm->ctx, "NetworkMonitor.change(): "); }
duk_pop(nm->ctx); // ...
ILibHashtable current = ILibDuktape_NetworkMonitor_CreateTable(nm->ctx);
ILibHashtable_Enumerate(current, ILibDuktape_NetworkMonitor_EventSink_OnEnumerateCurrent, (void*[]){ nm->ctx, "add", nm->emitter->object, nm->addressTable });
ILibHashtable_Enumerate(nm->addressTable, ILibDuktape_NetworkMonitor_EventSink_OnEnumerateCurrent, (void*[]) { nm->ctx, "remove", nm->emitter->object, current });
if (nm->OnAdded != NULL)
{
void *data[] = { nm->ctx, nm->OnAdded, nm->emitter->object, nm->addressTable };
ILibHashtable_Enumerate(current, ILibDuktape_NetworkMonitor_EventSink_OnEnumerateCurrent, data);
}
if(nm->OnRemoved != NULL)
{
void *data[] = { nm->ctx, nm->OnRemoved, nm->emitter->object, current };
ILibHashtable_Enumerate(nm->addressTable, ILibDuktape_NetworkMonitor_EventSink_OnEnumerateCurrent, data);
}
ILibHashtable_Destroy(nm->addressTable);
nm->addressTable = current;
@@ -130,9 +128,9 @@ void ILibDuktape_NetworkMonitor_PUSH(duk_context *ctx, void *chain)
nm->emitter = ILibDuktape_EventEmitter_Create(ctx);
nm->addressMonitor = ILibIPAddressMonitor_Create(chain, ILibDuktape_NetworkMonitor_EventSink, nm);
ILibDuktape_EventEmitter_CreateEvent(nm->emitter, "change", &(nm->OnChange));
ILibDuktape_EventEmitter_CreateEvent(nm->emitter, "add", &(nm->OnAdded));
ILibDuktape_EventEmitter_CreateEvent(nm->emitter, "remove", &(nm->OnRemoved));
ILibDuktape_EventEmitter_CreateEventEx(nm->emitter, "change");
ILibDuktape_EventEmitter_CreateEventEx(nm->emitter, "add");
ILibDuktape_EventEmitter_CreateEventEx(nm->emitter, "remove");
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_NetworkMonitor_Finalizer);
//

View File

@@ -1,3 +1,19 @@
/*
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef __ILIBDUKTAPE_NETWORKMONITOR__
#define __ILIBDUKTAPE_NETWORKMONITOR__

View File

@@ -1,3 +1,19 @@
/*
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "duktape.h"
#include "ILibDuktape_Helpers.h"
#include "ILibDuktapeModSearch.h"
@@ -9,7 +25,10 @@
#define ILibDuktape_Timer_Ptrs "\xFF_DuktapeTimer_PTRS"
#define ILibDuktape_Queue_Ptr "\xFF_Queue"
#define ILibDuktape_Stream_Buffer "\xFF_BUFFER"
#define ILibDuktape_Stream_ReadablePtr "\xFF_ReadablePtr"
int g_displayStreamPipeMessages = 0;
int g_displayFinalizerMessages = 0;
duk_ret_t ILibDuktape_Pollyfills_Buffer_slice(duk_context *ctx)
{
@@ -157,23 +176,23 @@ duk_ret_t ILibDuktape_Polyfills_Buffer_alloc(duk_context *ctx)
}
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);// [g][Duktape][Buffer][prototype][func]
duk_put_prop_string(ctx, -2, "readInt32BE"); // [g][Duktape][Buffer][prototype]
duk_pop_3(ctx); // [g]
//// 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);// [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]
//// 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]
// Polyfill Buffer.from()
duk_get_prop_string(ctx, -1, "Buffer"); // [g][Buffer]
@@ -313,6 +332,31 @@ duk_ret_t ILibDuktape_Polyfills_Console_enableWebLog(duk_context *ctx)
#endif
return (0);
}
duk_ret_t ILibDuktape_Polyfills_Console_displayStreamPipe_getter(duk_context *ctx)
{
duk_push_int(ctx, g_displayStreamPipeMessages);
return(1);
}
duk_ret_t ILibDuktape_Polyfills_Console_displayStreamPipe_setter(duk_context *ctx)
{
g_displayStreamPipeMessages = duk_require_int(ctx, 0);
return(0);
}
duk_ret_t ILibDuktape_Polyfills_Console_displayFinalizer_getter(duk_context *ctx)
{
duk_push_int(ctx, g_displayFinalizerMessages);
return(1);
}
duk_ret_t ILibDuktape_Polyfills_Console_displayFinalizer_setter(duk_context *ctx)
{
g_displayFinalizerMessages = duk_require_int(ctx, 0);
return(0);
}
duk_ret_t ILibDuktape_Polyfills_Console_logRefCount(duk_context *ctx)
{
printf("Reference Count => %s[%p]:%d\n", Duktape_GetStringPropertyValue(ctx, 0, ILibDuktape_OBJID, "UNKNOWN"), duk_require_heapptr(ctx, 0), ILibDuktape_GetReferenceCount(ctx, 0) - 1);
return(0);
}
void ILibDuktape_Polyfills_Console(duk_context *ctx)
{
// Polyfill console.log()
@@ -326,11 +370,12 @@ void ILibDuktape_Polyfills_Console(duk_context *ctx)
duk_dup(ctx, -1); // [g][console][console]
duk_put_prop_string(ctx, -3, "console"); // [g][console]
}
duk_push_c_function(ctx, ILibDuktape_Polyfills_Console_log, DUK_VARARGS); // [g][console][log]
duk_put_prop_string(ctx, -2, "log"); // [g][console]
ILibDuktape_CreateInstanceMethod(ctx, "log", ILibDuktape_Polyfills_Console_log, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "enableWebLog", ILibDuktape_Polyfills_Console_enableWebLog, 1);
ILibDuktape_CreateEventWithGetterAndSetterEx(ctx, "displayStreamPipeMessages", ILibDuktape_Polyfills_Console_displayStreamPipe_getter, ILibDuktape_Polyfills_Console_displayStreamPipe_setter);
ILibDuktape_CreateEventWithGetterAndSetterEx(ctx, "displayFinalizerMessages", ILibDuktape_Polyfills_Console_displayFinalizer_getter, ILibDuktape_Polyfills_Console_displayFinalizer_setter);
ILibDuktape_CreateInstanceMethod(ctx, "logReferenceCount", ILibDuktape_Polyfills_Console_logRefCount, 1);
duk_pop(ctx); // [g]
}
duk_ret_t ILibDuktape_ntohl(duk_context *ctx)
@@ -404,6 +449,14 @@ duk_ret_t ILibDuktape_Polyfills_timer_finalizer(duk_context *ctx)
// Make sure we remove any timers just in case, so we don't leak resources
ILibDuktape_Timer *ptrs;
duk_get_prop_string(ctx, 0, ILibDuktape_Timer_Ptrs);
if (duk_has_prop_string(ctx, 0, "\xFF_callback"))
{
duk_del_prop_string(ctx, 0, "\xFF_callback");
}
if (duk_has_prop_string(ctx, 0, "\xFF_argArray"))
{
duk_del_prop_string(ctx, 0, "\xFF_argArray");
}
ptrs = (ILibDuktape_Timer*)Duktape_GetBuffer(ctx, -1, NULL);
ILibLifeTime_Remove(ILibGetBaseTimer(Duktape_GetChain(ctx)), ptrs);
@@ -415,24 +468,29 @@ void ILibDuktape_Polyfills_timer_elapsed(void *obj)
int argCount, i;
duk_context *ctx = ptrs->ctx;
duk_push_heapptr(ctx, ptrs->callback); // [func]
duk_push_heapptr(ctx, ptrs->object); // [func][this]
duk_push_heapptr(ctx, ptrs->args); // [func][this][argArray]
if (ptrs->timerType == ILibDuktape_Timer_Type_INTERVAL)
{
ILibLifeTime_AddEx(ILibGetBaseTimer(Duktape_GetChain(ptrs->ctx)), ptrs, ptrs->timeout, ILibDuktape_Polyfills_timer_elapsed, NULL);
ILibLifeTime_AddEx(ILibGetBaseTimer(Duktape_GetChain(ctx)), ptrs, ptrs->timeout, ILibDuktape_Polyfills_timer_elapsed, NULL);
}
else
{
duk_del_prop_string(ctx, -2, "\xFF_callback");
duk_del_prop_string(ctx, -2, "\xFF_argArray");
}
duk_push_heapptr(ptrs->ctx, ptrs->callback); // [func]
duk_push_heapptr(ptrs->ctx, ptrs->object); // [func][this]
duk_push_heapptr(ptrs->ctx, ptrs->args); // [func][this][argArray]
argCount = (int)duk_get_length(ptrs->ctx, -1);
argCount = (int)duk_get_length(ctx, -1);
for (i = 0; i < argCount; ++i)
{
duk_get_prop_index(ptrs->ctx, -1, i); // [func][this][argArray][arg]
duk_swap_top(ptrs->ctx, -2); // [func][this][arg][argArray]
duk_get_prop_index(ctx, -1, i); // [func][this][argArray][arg]
duk_swap_top(ctx, -2); // [func][this][arg][argArray]
}
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(ctx); // ...
duk_pop(ctx); // [func][this][...arg...]
if (duk_pcall_method(ctx, argCount) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "timers.onElapsed() callback handler"); }
duk_pop(ctx); // ...
}
duk_ret_t ILibDuktape_Polyfills_timer_set(duk_context *ctx)
{
@@ -447,6 +505,18 @@ duk_ret_t ILibDuktape_Polyfills_timer_set(duk_context *ctx)
timerType = (ILibDuktape_Timer_Type)duk_get_int(ctx, -1);
duk_push_object(ctx); //[retVal]
switch (timerType)
{
case ILibDuktape_Timer_Type_IMMEDIATE:
ILibDuktape_WriteID(ctx, "Timers.immediate");
break;
case ILibDuktape_Timer_Type_INTERVAL:
ILibDuktape_WriteID(ctx, "Timers.interval");
break;
case ILibDuktape_Timer_Type_TIMEOUT:
ILibDuktape_WriteID(ctx, "Timers.timeout");
break;
}
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_Polyfills_timer_finalizer);
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_Timer)); //[retVal][ptrs]
ptrs = (ILibDuktape_Timer*)Duktape_GetBuffer(ctx, -1, NULL);
@@ -463,13 +533,13 @@ duk_ret_t ILibDuktape_Polyfills_timer_set(duk_context *ctx)
for (argx = ILibDuktape_Timer_Type_IMMEDIATE == timerType ? 1 : 2; argx < nargs; ++argx)
{
duk_dup(ctx, argx); //[retVal][argArray][arg]
duk_put_prop_index(ctx, -2, argx - (ILibDuktape_Timer_Type_IMMEDIATE == timerType ? 1 : 2)); //[retVal][argArray]
duk_put_prop_index(ctx, -2, argx - (ILibDuktape_Timer_Type_IMMEDIATE == timerType ? 1 : 2));//[retVal][argArray]
}
ptrs->args = duk_get_heapptr(ctx, -1);
ptrs->args = duk_get_heapptr(ctx, -1); //[retVal]
duk_put_prop_string(ctx, -2, "\xFF_argArray");
duk_dup(ctx, 0); //[retVal][callback]
duk_put_prop_string(ctx, -2, "\xFF_callback"); //[retVal]
duk_dup(ctx, 0); //[retVal][callback]
duk_put_prop_string(ctx, -2, "\xFF_callback"); //[retVal]
ILibLifeTime_AddEx(ILibGetBaseTimer(chain), ptrs, ptrs->timeout, ILibDuktape_Polyfills_timer_elapsed, NULL);
return 1;
@@ -758,11 +828,179 @@ void ILibDuktape_DynamicBuffer_Push(duk_context *ctx, void *chain)
duk_push_c_function(ctx, ILibDuktape_DynamicBuffer_new, DUK_VARARGS);
}
duk_ret_t ILibDuktape_Polyfills_debugCrash(duk_context *ctx)
{
void *p = NULL;
((int*)p)[0] = 55;
return(0);
}
void ILibDuktape_Stream_PauseSink(struct ILibDuktape_readableStream *sender, void *user)
{
}
void ILibDuktape_Stream_ResumeSink(struct ILibDuktape_readableStream *sender, void *user)
{
int skip = 0;
duk_size_t bufferLen;
duk_push_heapptr(sender->ctx, sender->object); // [stream]
void *func = Duktape_GetHeapptrProperty(sender->ctx, -1, "_read");
duk_pop(sender->ctx); // ...
while (func != NULL && sender->paused == 0)
{
duk_push_heapptr(sender->ctx, sender->object); // [this]
if (!skip && duk_has_prop_string(sender->ctx, -1, ILibDuktape_Stream_Buffer))
{
duk_get_prop_string(sender->ctx, -1, ILibDuktape_Stream_Buffer); // [this][buffer]
if ((bufferLen = duk_get_length(sender->ctx, -1)) > 0)
{
// Buffer is not empty, so we need to 'PUSH' it
duk_get_prop_string(sender->ctx, -2, "push"); // [this][buffer][push]
duk_dup(sender->ctx, -3); // [this][buffer][push][this]
duk_dup(sender->ctx, -3); // [this][buffer][push][this][buffer]
duk_remove(sender->ctx, -4); // [this][push][this][buffer]
duk_call_method(sender->ctx, 1); // [this][boolean]
sender->paused = !duk_get_boolean(sender->ctx, -1);
duk_pop(sender->ctx); // [this]
if (duk_has_prop_string(sender->ctx, -1, ILibDuktape_Stream_Buffer))
{
duk_get_prop_string(sender->ctx, -1, ILibDuktape_Stream_Buffer); // [this][buffer]
if (duk_get_length(sender->ctx, -1) == bufferLen)
{
// All the data was unshifted
skip = !sender->paused;
}
duk_pop(sender->ctx); // [this]
}
duk_pop(sender->ctx); // ...
}
else
{
// Buffer is empty
duk_pop(sender->ctx); // [this]
duk_del_prop_string(sender->ctx, -1, ILibDuktape_Stream_Buffer);
duk_pop(sender->ctx); // ...
}
}
else
{
// We need to 'read' more data
duk_push_heapptr(sender->ctx, func); // [this][read]
duk_swap_top(sender->ctx, -2); // [read][this]
if (duk_pcall_method(sender->ctx, 0) != 0) { ILibDuktape_Process_UncaughtException(sender->ctx); duk_pop(sender->ctx); break; }
// // [buffer]
duk_push_heapptr(sender->ctx, sender->object); // [buffer][this]
duk_swap_top(sender->ctx, -2); // [this][buffer]
if (duk_has_prop_string(sender->ctx, -2, ILibDuktape_Stream_Buffer))
{
duk_push_global_object(sender->ctx); // [this][buffer][g]
duk_get_prop_string(sender->ctx, -1, "Buffer"); // [this][buffer][g][Buffer]
duk_remove(sender->ctx, -2); // [this][buffer][Buffer]
duk_get_prop_string(sender->ctx, -1, "concat"); // [this][buffer][Buffer][concat]
duk_swap_top(sender->ctx, -2); // [this][buffer][concat][this]
duk_push_array(sender->ctx); // [this][buffer][concat][this][Array]
duk_get_prop_string(sender->ctx, -1, "push"); // [this][buffer][concat][this][Array][push]
duk_dup(sender->ctx, -2); // [this][buffer][concat][this][Array][push][this]
duk_get_prop_string(sender->ctx, -7, ILibDuktape_Stream_Buffer); // [this][buffer][concat][this][Array][push][this][buffer]
duk_call_method(sender->ctx, 1); duk_pop(sender->ctx); // [this][buffer][concat][this][Array]
duk_get_prop_string(sender->ctx, -1, "push"); // [this][buffer][concat][this][Array][push]
duk_dup(sender->ctx, -2); // [this][buffer][concat][this][Array][push][this]
duk_dup(sender->ctx, -6); // [this][buffer][concat][this][Array][push][this][buffer]
duk_remove(sender->ctx, -7); // [this][concat][this][Array][push][this][buffer]
duk_call_method(sender->ctx, 1); duk_pop(sender->ctx); // [this][concat][this][Array]
duk_call_method(sender->ctx, 1); // [this][buffer]
}
duk_put_prop_string(sender->ctx, -2, ILibDuktape_Stream_Buffer); // [this]
duk_pop(sender->ctx); // ...
skip = 0;
}
}
}
int ILibDuktape_Stream_UnshiftSink(struct ILibDuktape_readableStream *sender, int unshiftBytes, void *user)
{
duk_push_fixed_buffer(sender->ctx, unshiftBytes); // [buffer]
memcpy_s(Duktape_GetBuffer(sender->ctx, -1, NULL), unshiftBytes, sender->unshiftReserved, unshiftBytes);
duk_push_heapptr(sender->ctx, sender->object); // [buffer][stream]
duk_push_buffer_object(sender->ctx, -2, 0, unshiftBytes, DUK_BUFOBJ_NODEJS_BUFFER); // [buffer][stream][buffer]
duk_put_prop_string(sender->ctx, -2, ILibDuktape_Stream_Buffer); // [buffer][stream]
duk_pop_2(sender->ctx); // ...
return(unshiftBytes);
}
duk_ret_t ILibDuktape_Stream_Push(duk_context *ctx)
{
duk_push_this(ctx); // [stream]
ILibDuktape_readableStream *RS = (ILibDuktape_readableStream*)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_Stream_ReadablePtr);
duk_get_prop_string(ctx, -1, ILibDuktape_Stream_Buffer); // [stream][buffer]
duk_del_prop_string(ctx, -2, ILibDuktape_Stream_Buffer); // (Deleting here, because unshift will save it again, if necessary)
duk_size_t bufferLen;
char *buffer = (char*)Duktape_GetBuffer(ctx, -1, &bufferLen);
duk_push_boolean(ctx, !ILibDuktape_readableStream_WriteDataEx(RS, 0, buffer, (int)bufferLen)); // [stream][buffer][retVal]
return(1);
}
duk_ret_t ILibDuktape_Stream_EndSink(duk_context *ctx)
{
duk_push_this(ctx); // [stream]
ILibDuktape_readableStream *RS = (ILibDuktape_readableStream*)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_Stream_ReadablePtr);
ILibDuktape_readableStream_WriteEnd(RS);
return(0);
}
duk_idx_t ILibDuktape_Stream_newReadable(duk_context *ctx)
{
ILibDuktape_readableStream *RS;
duk_push_object(ctx); // [Readable]
ILibDuktape_WriteID(ctx, "stream.readable");
RS = ILibDuktape_ReadableStream_InitEx(ctx, ILibDuktape_Stream_PauseSink, ILibDuktape_Stream_ResumeSink, ILibDuktape_Stream_UnshiftSink, NULL);
RS->paused = 1;
duk_push_pointer(ctx, RS);
duk_put_prop_string(ctx, -2, ILibDuktape_Stream_ReadablePtr);
ILibDuktape_CreateInstanceMethod(ctx, "push", ILibDuktape_Stream_Push, DUK_VARARGS);
ILibDuktape_EventEmitter_AddOnceEx3(ctx, -1, "end", ILibDuktape_Stream_EndSink);
if (duk_is_object(ctx, 0))
{
void *h = Duktape_GetHeapptrProperty(ctx, 0, "read");
if (h != NULL) { duk_push_heapptr(ctx, h); duk_put_prop_string(ctx, -2, "_read"); }
}
return(1);
}
void ILibDuktape_Stream_Init(duk_context *ctx, void *chain)
{
duk_push_object(ctx); // [stream
ILibDuktape_WriteID(ctx, "stream");
ILibDuktape_CreateInstanceMethod(ctx, "Readable", ILibDuktape_Stream_newReadable, DUK_VARARGS);
}
void ILibDuktape_Polyfills_debugGC2(duk_context *ctx, void ** args, int argsLen)
{
if (g_displayFinalizerMessages) { printf("=> GC();\n"); }
duk_gc(ctx, 0);
duk_gc(ctx, 0);
}
duk_ret_t ILibDuktape_Polyfills_debugGC(duk_context *ctx)
{
ILibDuktape_Immediate(ctx, (void*[]) { NULL }, 0, ILibDuktape_Polyfills_debugGC2);
return(0);
}
duk_ret_t ILibDuktape_Polyfills_debug(duk_context *ctx)
{
#ifdef WIN32
if (IsDebuggerPresent()) { __debugbreak(); }
#elif defined(_POSIX)
raise(SIGTRAP);
#endif
return(0);
}
void ILibDuktape_Polyfills_Init(duk_context *ctx)
{
ILibDuktape_ModSearch_AddHandler(ctx, "queue", ILibDuktape_Queue_Push);
ILibDuktape_ModSearch_AddHandler(ctx, "DynamicBuffer", ILibDuktape_DynamicBuffer_Push);
ILibDuktape_ModSearch_AddHandler(ctx, "stream", ILibDuktape_Stream_Init);
// Global Polyfills
duk_push_global_object(ctx); // [g]
@@ -774,6 +1012,9 @@ void ILibDuktape_Polyfills_Init(duk_context *ctx)
ILibDuktape_Polyfills_timer(ctx);
ILibDuktape_CreateInstanceMethod(ctx, "addModule", ILibDuktape_Polyfills_addModule, 2);
ILibDuktape_CreateInstanceMethod(ctx, "_debugCrash", ILibDuktape_Polyfills_debugCrash, 0);
ILibDuktape_CreateInstanceMethod(ctx, "_debugGC", ILibDuktape_Polyfills_debugGC, 0);
ILibDuktape_CreateInstanceMethod(ctx, "_debug", ILibDuktape_Polyfills_debug, 0);
duk_pop(ctx); // ...
}

View File

@@ -1,8 +1,26 @@
/*
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef __ILibDuktape_Polyfills__
#define __ILibDuktape_Polyfills__
#include "duktape.h"
extern int g_displayStreamPipeMessages;
extern int g_displayFinalizerMessages;
void ILibDuktape_Polyfills_Init(duk_context *ctx);
#endif

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006 - 2017 Intel Corporation
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ limitations under the License.
#include "ILibParsers_Duktape.h"
#include "microstack/ILibParsers.h"
#include "ILibDuktape_EventEmitter.h"
#include "ILibDuktape_Polyfills.h"
#define ILibDuktape_readableStream_WritePipes "\xFF_WritePipes"
@@ -105,6 +106,19 @@ typedef struct ILibDuktape_readableStream_bufferedData
char buffer[];
}ILibDuktape_readableStream_bufferedData;
void ILibDuktape_ReadableStream_DestroyPausedData(ILibDuktape_readableStream *stream)
{
ILibDuktape_readableStream_bufferedData *buffered = (ILibDuktape_readableStream_bufferedData*)stream->paused_data;
ILibDuktape_readableStream_bufferedData *tmp;
while (buffered != NULL)
{
tmp = buffered->Next;
free(buffered);
buffered = tmp;
}
stream->paused_data = NULL;
}
void ILibDuktape_readableStream_WriteData_buffer(ILibDuktape_readableStream *stream, int streamReserved, char *buffer, int bufferLen)
{
ILibDuktape_readableStream_bufferedData *buffered = (ILibDuktape_readableStream_bufferedData*)ILibMemory_Allocate(bufferLen + sizeof(ILibDuktape_readableStream_bufferedData), 0, NULL, NULL);
@@ -137,17 +151,17 @@ void ILibDuktape_readableStream_WriteData_OnData_ChainThread(void *chain, void *
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]
ILibDuktape_EventEmitter_SetupEmit(stream->ctx, stream->object, "data"); // [ext][emit][this][data]
if (data->Reserved == 0)
{
duk_push_buffer_object(stream->ctx, -3, 0, data->bufferLen, DUK_BUFOBJ_NODEJS_BUFFER); // [ext][func][this][buffer]
duk_push_buffer_object(stream->ctx, -4, 0, data->bufferLen, DUK_BUFOBJ_NODEJS_BUFFER); // [ext][emit][this][data][buffer]
}
else
{
duk_push_lstring(stream->ctx, data->buffer, data->bufferLen); // [ext][func][this][buffer/string]
duk_push_lstring(stream->ctx, data->buffer, data->bufferLen); // [ext][emit][this][data][buffer/string]
}
if (duk_pcall_method(stream->ctx, 1) != 0) // [...][retVal]
if (duk_pcall_method(stream->ctx, 2) != 0) // [...][retVal]
{
ILibDuktape_Process_UncaughtException(stream->ctx);
}
@@ -275,6 +289,7 @@ int ILibDuktape_readableStream_WriteDataEx(ILibDuktape_readableStream *stream, i
{
ILibDuktape_WritableStream *ws = (ILibDuktape_WritableStream*)w->nativeWritable;
ws->Reserved = streamReserved;
ws->endBytes = -1;
switch (ws->WriteSink(ws, buffer, bufferLen, ws->WriteSink_User))
{
case ILibTransport_DoneState_INCOMPLETE:
@@ -333,7 +348,7 @@ int ILibDuktape_readableStream_WriteDataEx(ILibDuktape_readableStream *stream, i
stream->pipeInProgress = 0;
sem_post(&(stream->pipeLock));
if (stream->OnData != NULL)
if(ILibDuktape_EventEmitter_HasListeners(stream->emitter, "data"))
{
if (ILibIsRunningOnChainThread(stream->chain))
{
@@ -342,17 +357,16 @@ int ILibDuktape_readableStream_WriteDataEx(ILibDuktape_readableStream *stream, i
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]
ILibDuktape_EventEmitter_SetupEmit(stream->ctx, stream->object, "data"); // [extBuffer][emit][this][data]
if (streamReserved == 0)
{
duk_push_buffer_object(stream->ctx, -3, 0, bufferLen, DUK_BUFOBJ_NODEJS_BUFFER); // [extBuffer][func][this][nodeBuffer]
duk_push_buffer_object(stream->ctx, -4, 0, bufferLen, DUK_BUFOBJ_NODEJS_BUFFER); // [extBuffer][emit][this][data][nodeBuffer]
}
else
{
duk_push_lstring(stream->ctx, buffer, bufferLen); // [func][this][string]
duk_push_lstring(stream->ctx, buffer, bufferLen); // [extBuffer][emit][this][data][string]
}
if (duk_pcall_method(stream->ctx, 1) != 0) // [retVal]
if (duk_pcall_method(stream->ctx, 2) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(stream->ctx);
}
@@ -377,14 +391,14 @@ int ILibDuktape_readableStream_WriteDataEx(ILibDuktape_readableStream *stream, i
ILibChain_RunOnMicrostackThread(stream->chain, ILibDuktape_readableStream_WriteData_OnData_ChainThread, tmp);
}
}
else if (stream->PauseHandler != NULL && stream->OnEnd == NULL)
else if (stream->PauseHandler != NULL && ILibDuktape_EventEmitter_HasListeners(stream->emitter, "end") == 0)
{
// 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)
else if (ILibDuktape_EventEmitter_HasListeners(stream->emitter, "end") != 0)
{
return 0;
}
@@ -429,16 +443,11 @@ int ILibDuktape_readableStream_WriteEnd(ILibDuktape_readableStream *stream)
retVal = 0;
}
}
else if (stream->OnEnd != NULL)
else if (ILibDuktape_EventEmitter_HasListeners(stream->emitter, "end") != 0)
{
duk_context *x = stream->ctx;
duk_push_heapptr(stream->ctx, stream->OnEnd); // [func]
duk_push_heapptr(stream->ctx, stream->object); // [func][this]
if (duk_pcall_method(stream->ctx, 0) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(stream->ctx);
}
duk_pop(x); // ...
ILibDuktape_EventEmitter_SetupEmit(stream->ctx, stream->object, "end"); // [emit][this][end]
if (duk_pcall_method(stream->ctx, 1) != 0) { ILibDuktape_Process_UncaughtException(stream->ctx); }
duk_pop(stream->ctx); // ...
retVal = 0;
}
}
@@ -447,16 +456,18 @@ int ILibDuktape_readableStream_WriteEnd(ILibDuktape_readableStream *stream)
void ILibDuktape_readableStream_Closed(ILibDuktape_readableStream *stream)
{
ILibDuktape_readableStream_WriteEnd(stream);
if (stream->OnClose != NULL)
if(ILibDuktape_EventEmitter_HasListeners(stream->emitter, "close")!=0)
{
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]
{
ILibDuktape_Process_UncaughtException(stream->ctx);
}
duk_pop(stream->ctx); // ...
ILibDuktape_EventEmitter_SetupEmit(stream->ctx, stream->object, "close"); // [emit][this][close]
if (duk_pcall_method(stream->ctx, 1) != 0) { ILibDuktape_Process_UncaughtException(stream->ctx); }
duk_pop(stream->ctx); // ...
}
duk_push_heapptr(stream->ctx, stream->object); // [stream]
duk_get_prop_string(stream->ctx, -1, "unpipe"); // [stream][unpipe]
duk_swap_top(stream->ctx, -2); // [unpipe][this]
if (duk_pcall_method(stream->ctx, 0) != 0) { ILibDuktape_Process_UncaughtException(stream->ctx); }
duk_pop(stream->ctx); // ...
}
duk_ret_t ILibDuktape_readableStream_pause(duk_context *ctx)
@@ -482,7 +493,7 @@ duk_ret_t ILibDuktape_readableStream_pause(duk_context *ctx)
int ILibDuktape_readableStream_resume_flush(ILibDuktape_readableStream *rs)
{
// Sanity check, and make sure there is a listener first, otherwise we're wasting our time
if (rs->OnData == NULL && rs->nextWriteable == NULL && rs->OnEnd == NULL)
if(ILibDuktape_EventEmitter_HasListeners(rs->emitter, "data")==0 && rs->nextWriteable == NULL && ILibDuktape_EventEmitter_HasListeners(rs->emitter, "end")==0)
{
return 1; // No listeners....
}
@@ -528,12 +539,23 @@ duk_ret_t ILibDuktape_readableStream_resume(duk_context *ctx)
void ILibDuktape_ReadableStream_pipe_ResumeLater(duk_context *ctx, void **args, int argsLen)
{
ILibDuktape_readableStream *rs = (ILibDuktape_readableStream*)args[0];
rs->resumeImmediate = NULL;
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_later(duk_context *ctx, void **args, int argsLen)
{
duk_push_heapptr(ctx, args[0]); // [readable]
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS);
ILibDuktape_readableStream *rs = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop(ctx);
duk_push_heapptr(ctx, rs->pipeImmediate);
duk_del_prop_string(ctx, -1, "dest");
duk_pop(ctx);
rs->pipeImmediate = NULL;
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]
@@ -557,8 +579,10 @@ duk_ret_t ILibDuktape_readableStream_pipe(duk_context *ctx)
{
// 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);
rstream->pipeImmediate = 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_heapptr(ctx, rstream->pipeImmediate); // [immediate]
duk_dup(ctx, 0); // [immediate][ws]
duk_put_prop_string(ctx, -2, "dest"); // [immediate]
duk_dup(ctx, 0);
sem_post(&(rstream->pipeLock));
return(1);
@@ -615,12 +639,14 @@ duk_ret_t ILibDuktape_readableStream_pipe(duk_context *ctx)
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);
rstream->resumeImmediate = ILibDuktape_Immediate(ctx, (void*[]) { rstream, duk_get_heapptr(ctx, 0) }, 1, ILibDuktape_ReadableStream_pipe_ResumeLater);
duk_push_heapptr(ctx, rstream->resumeImmediate); // [immediate]
duk_push_this(ctx); // [immediate][this]
duk_put_prop_string(ctx, -2, "self"); // [immediate]
duk_pop(ctx); // ...
}
else
{
@@ -646,7 +672,12 @@ void ILibDuktape_readableStream_unpipe_later(duk_context *ctx, void ** args, int
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);
void *imm = ILibDuktape_Immediate(ctx, (void*[]) { args[0], args[1] }, argsLen, ILibDuktape_readableStream_unpipe_later);
duk_push_heapptr(ctx, imm); // [immediate]
duk_push_heapptr(ctx, args[0]); // [immediate][this]
duk_put_prop_string(ctx, -2, "\xFF_Self"); // [immediate]
if (args[1] != NULL) { duk_push_heapptr(ctx, args[1]); duk_put_prop_string(ctx, -2, "\xFF_w"); }
duk_pop(ctx); // ...
sem_post(&(data->pipeLock));
return;
}
@@ -683,11 +714,11 @@ void ILibDuktape_readableStream_unpipe_later(duk_context *ctx, void ** args, int
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])))
if(duk_get_heapptr(ctx, -1) == args[1])
{
if (g_displayFinalizerMessages) { printf("*** UNPIPE/Removing Reference to Writeable: %s (RefCount: %d)\n", Duktape_GetStringPropertyValue(ctx, -1, ILibDuktape_OBJID, "UNKNOWN"), ILibDuktape_GetReferenceCount(ctx, -1)); }
// Removing the entry from the Array
duk_pop_2(ctx); // [array]
duk_pop(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]
@@ -707,10 +738,10 @@ void ILibDuktape_readableStream_unpipe_later(duk_context *ctx, void ** args, int
else
{
// 'unpipe' all pipes
w = data->nextWriteable;
while (w != NULL)
{
duk_push_heapptr(ctx, w->writableStream); // [ws]
if (g_displayFinalizerMessages) { printf("*** UNPIPE/Removing Reference to Writeable: %s (RefCount: %d)\n", Duktape_GetStringPropertyValue(ctx, -1, ILibDuktape_OBJID, "UNKNOWN"), ILibDuktape_GetReferenceCount(ctx, -1)); }
duk_get_prop_string(ctx, -1, "emit"); // [ws][emit]
duk_swap_top(ctx, -2); // [emit][this]
duk_push_string(ctx, "unpipe"); // [emit][this][unpipe]
@@ -752,7 +783,13 @@ duk_ret_t ILibDuktape_readableStream_unpipe(duk_context *ctx)
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);
void *imm = ILibDuktape_Immediate(ctx, (void*[]) { duk_get_heapptr(ctx, -1), nargs == 1 ? duk_get_heapptr(ctx, 0) : NULL }, nargs + 1, ILibDuktape_readableStream_unpipe_later);
duk_push_heapptr(ctx, imm); // [immediate]
duk_push_this(ctx); // [immediate][this]
duk_put_prop_string(ctx, -2, "\xFF_Self"); // [immediate]
if (nargs == 1) { duk_dup(ctx, 0); duk_put_prop_string(ctx, -2, "\xFF_w"); }
duk_pop(ctx); // ...
return 0;
}
duk_ret_t ILibDuktape_readableStream_isPaused(duk_context *ctx)
@@ -777,13 +814,23 @@ duk_ret_t ILibDuktape_readableStream_pipe_getter(duk_context *ctx)
duk_push_c_function(ctx, ILibDuktape_readableStream_pipe, DUK_VARARGS);
return 1;
}
void ILibDuktape_ReadableStream_PipeLockFinalizer(duk_context *ctx, void *stream)
duk_ret_t ILibDuktape_ReadableStream_PipeLockFinalizer(duk_context *ctx)
{
ILibDuktape_readableStream_bufferedData *tmp;
ILibDuktape_readableStream *ptrs;
duk_push_heapptr(ctx, stream); // [stream]
duk_push_this(ctx); // [stream]
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [stream][buffer]
ptrs = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
if (ptrs->pipeImmediate != NULL)
{
duk_push_global_object(ctx); // [g]
duk_get_prop_string(ctx, -1, "clearImmediate"); // [g][clearImmediate]
duk_swap_top(ctx, -2); // [clearImmediate][this]
duk_push_heapptr(ctx, ptrs->pipeImmediate); // [clearImmediate][this][immedate]
duk_call_method(ctx, 1); duk_pop(ctx); // ...
ptrs->pipeImmediate = NULL;
}
while ((tmp = (ILibDuktape_readableStream_bufferedData*)ptrs->paused_data) != NULL)
{
@@ -794,6 +841,7 @@ void ILibDuktape_ReadableStream_PipeLockFinalizer(duk_context *ctx, void *stream
sem_destroy(&(ptrs->pipeLock));
duk_pop_2(ctx);
return(0);
}
duk_ret_t ILibDuktape_ReadableStream_unshift(duk_context *ctx)
{
@@ -809,7 +857,7 @@ duk_ret_t ILibDuktape_ReadableStream_unshift(duk_context *ctx)
else
{
duk_size_t bufferLen;
Duktape_GetBuffer(ctx, 0, &bufferLen);
rs->unshiftReserved = (char*)Duktape_GetBuffer(ctx, 0, &bufferLen);
duk_push_int(ctx, rs->UnshiftHandler(rs, (int)bufferLen, rs->user));
return(1);
}
@@ -831,7 +879,6 @@ ILibDuktape_readableStream* ILibDuktape_ReadableStream_InitEx(duk_context *ctx,
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);
retVal->object = duk_get_heapptr(ctx, -1);
@@ -840,12 +887,12 @@ ILibDuktape_readableStream* ILibDuktape_ReadableStream_InitEx(duk_context *ctx,
retVal->ResumeHandler = OnResume;
retVal->UnshiftHandler = OnUnshift;
sem_init(&(retVal->pipeLock), 0, 1);
ILibDuktape_CreateIndependentFinalizer(ctx, ILibDuktape_ReadableStream_PipeLockFinalizer);
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_ReadableStream_PipeLockFinalizer);
emitter = ILibDuktape_EventEmitter_Create(ctx);
ILibDuktape_EventEmitter_CreateEvent(emitter, "end", &(retVal->OnEnd));
ILibDuktape_EventEmitter_CreateEvent(emitter, "data", &(retVal->OnData));
ILibDuktape_EventEmitter_CreateEvent(emitter, "close", &(retVal->OnClose));
retVal->emitter = emitter = ILibDuktape_EventEmitter_Create(ctx);
ILibDuktape_EventEmitter_CreateEventEx(emitter, "end");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "data");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "close");
ILibDuktape_CreateInstanceMethod(ctx, "pause", ILibDuktape_readableStream_pause, 0);
ILibDuktape_CreateInstanceMethod(ctx, "resume", ILibDuktape_readableStream_resume, 0);

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006 - 2017 Intel Corporation
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ limitations under the License.
#include "duktape.h"
#include "microstack/ILibParsers.h"
#include "ILibDuktape_EventEmitter.h"
#define ILibDuktape_readableStream_RSPTRS "\xFF_ReadableStream_PTRS"
@@ -39,9 +40,6 @@ typedef struct ILibDuktape_readableStream
duk_context *ctx;
void *chain;
void *object;
void *OnClose;
void *OnData;
void *OnEnd;
void *user;
void *pipeArray;
@@ -64,6 +62,10 @@ typedef struct ILibDuktape_readableStream
ILibDuktape_readableStream_PauseResumeHandler ResumeHandler;
ILibDuktape_readableStream_MethodHookHandler PipeHookHandler;
ILibDuktape_readableStream_UnShiftHandler UnshiftHandler;
ILibDuktape_EventEmitter *emitter;
char *unshiftReserved;
void *resumeImmediate;
void *pipeImmediate;
}ILibDuktape_readableStream;
ILibDuktape_readableStream* ILibDuktape_ReadableStream_InitEx(duk_context *ctx, ILibDuktape_readableStream_PauseResumeHandler OnPause, ILibDuktape_readableStream_PauseResumeHandler OnResume, ILibDuktape_readableStream_UnShiftHandler OnUnshift, void *user);
@@ -71,6 +73,7 @@ ILibDuktape_readableStream* ILibDuktape_ReadableStream_InitEx(duk_context *ctx,
#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;
void ILibDuktape_ReadableStream_DestroyPausedData(ILibDuktape_readableStream *stream);
int ILibDuktape_readableStream_WriteDataEx(ILibDuktape_readableStream *stream, int streamReserved, char* buffer, int bufferLen);
int ILibDuktape_readableStream_WriteEnd(ILibDuktape_readableStream *stream);
#define ILibDuktape_readableStream_WriteData(stream, buffer, bufferLen) ILibDuktape_readableStream_WriteDataEx(stream, 0, buffer, bufferLen)

View File

@@ -1,3 +1,19 @@
/*
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "ILibDuktape_SHA256.h"
#include "duktape.h"
#include "ILibDuktape_Helpers.h"
@@ -21,8 +37,6 @@ typedef struct ILibDuktape_SHA256_Data
duk_context *ctx;
void *object;
void *OnHash;
void *OnHashString;
char buffer[33];
SHA256_CTX shctx;
}ILibDuktape_SHA256_Data;
@@ -31,8 +45,6 @@ typedef struct ILibDuktape_SHA512_Data
duk_context *ctx;
void *object;
void *OnHash;
void *OnHashString;
char buffer[65];
SHA512_CTX shctx;
}ILibDuktape_SHA512_Data;
@@ -41,8 +53,6 @@ typedef struct ILibDuktape_MD5_Data
duk_context *ctx;
void *object;
void *OnHash;
void *OnHashString;
char buffer[33];
MD5_CTX mctx;
}ILibDuktape_MD5_Data;
@@ -82,34 +92,21 @@ ILibTransport_DoneState ILibDuktape_SHA384_Write(struct ILibDuktape_WritableStre
}
void ILibDuktape_SHA256_End(struct ILibDuktape_WritableStream *stream, void *user)
{
ILibDuktape_SHA256_Data *data = (ILibDuktape_SHA256_Data*)user;
data->buffer[32] = 0;
SHA256_Final((unsigned char*)data->buffer, &(data->shctx));
if (data->ctx != NULL && data->OnHash != NULL)
{
duk_push_heapptr(data->ctx, data->OnHash); // [func]
duk_push_heapptr(data->ctx, data->object); // [func][this]
duk_push_external_buffer(data->ctx); // [func][this][hash]
duk_config_buffer(data->ctx, -1, data->buffer, 32);
if (duk_pcall_method(data->ctx, 1) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(data->ctx);
}
duk_pop(data->ctx); // ...
}
if (data->ctx != NULL && data->OnHashString != NULL)
{
duk_push_heapptr(data->ctx, data->OnHashString); // [func]
duk_push_heapptr(data->ctx, data->object); // [func][this]
duk_push_string(data->ctx, util_tohex(data->buffer, 32, ILibScratchPad)); // [func][this][hashString]
if (duk_pcall_method(data->ctx, 1) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(data->ctx);
}
duk_pop(data->ctx); // ...
}
duk_push_external_buffer(data->ctx); // [extBuffer]
duk_config_buffer(data->ctx, -1, data->buffer, 32);
ILibDuktape_EventEmitter_SetupEmit(data->ctx, data->object, "hash"); // [extBuffer][emit][this]['hash']
duk_push_buffer_object(data->ctx, -4, 0, 32, DUK_BUFOBJ_NODEJS_BUFFER); // [extBuffer][emit][this]['hash'][hash]
if (duk_pcall_method(data->ctx, 2) != 0) { ILibDuktape_Process_UncaughtException(data->ctx); }
duk_pop_2(data->ctx); // ...
ILibDuktape_EventEmitter_SetupEmit(data->ctx, data->object, "hashString"); // [emit][this]['hash']
duk_push_string(data->ctx, util_tohex(data->buffer, 32, ILibScratchPad)); // [emit][this]['hash'][hashString]
if (duk_pcall_method(data->ctx, 1) != 0) { ILibDuktape_Process_UncaughtException(data->ctx); }
duk_pop(data->ctx); // ...
}
void ILibDuktape_SHA384_End(struct ILibDuktape_WritableStream *stream, void *user)
{
@@ -117,29 +114,17 @@ void ILibDuktape_SHA384_End(struct ILibDuktape_WritableStream *stream, void *use
data->buffer[48] = 0;
SHA384_Final((unsigned char*)data->buffer, &(data->shctx));
if (data->ctx != NULL && data->OnHash != NULL)
{
duk_push_heapptr(data->ctx, data->OnHash); // [func]
duk_push_heapptr(data->ctx, data->object); // [func][this]
duk_push_external_buffer(data->ctx); // [func][this][hash]
duk_config_buffer(data->ctx, -1, data->buffer, 48);
if (duk_pcall_method(data->ctx, 1) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(data->ctx);
}
duk_pop(data->ctx); // ...
}
if (data->ctx != NULL && data->OnHashString != NULL)
{
duk_push_heapptr(data->ctx, data->OnHashString); // [func]
duk_push_heapptr(data->ctx, data->object); // [func][this]
duk_push_string(data->ctx, util_tohex(data->buffer, 48, ILibScratchPad)); // [func][this][hashString]
if (duk_pcall_method(data->ctx, 1) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(data->ctx);
}
duk_pop(data->ctx); // ...
}
duk_push_external_buffer(data->ctx); // [extBuffer]
duk_config_buffer(data->ctx, -1, data->buffer, 48);
ILibDuktape_EventEmitter_SetupEmit(data->ctx, data->object, "hash"); // [extBuffer][emit][this]['hash']
duk_push_buffer_object(data->ctx, -4, 0, 48, DUK_BUFOBJ_NODEJS_BUFFER); // [extBuffer][emit][this]['hash'][hash]
if (duk_pcall_method(data->ctx, 2) != 0) { ILibDuktape_Process_UncaughtException(data->ctx); }
duk_pop_2(data->ctx); // ...
ILibDuktape_EventEmitter_SetupEmit(data->ctx, data->object, "hashString"); // [emit][this]['hashString']
duk_push_string(data->ctx, util_tohex(data->buffer, 48, ILibScratchPad)); // [emit][this]['hashString'][hashString]
if (duk_pcall_method(data->ctx, 2) != 0) { ILibDuktape_Process_UncaughtException(data->ctx); }
duk_pop(data->ctx); // ...
}
duk_ret_t ILibDuktape_SHA256_SIGNER_Finalizer(duk_context *ctx)
{
@@ -175,7 +160,7 @@ void ILibDuktape_SHA256_SIGNER_End(struct ILibDuktape_WritableStream *stream, vo
duk_swap_top(data->ctx, -2); // [sigBuffer][signer]
duk_push_heapptr(data->ctx, data->OnSignature); // [sigBuffer][signer][func]
duk_swap_top(data->ctx, -2); // [sigBuffer][func][signer/this]
duk_push_buffer_object(data->ctx, -3, 0, len, DUK_BUFOBJ_DUKTAPE_BUFFER); // [sigBuffer][func][signer/this][bufView]
duk_push_buffer_object(data->ctx, -3, 0, len, DUK_BUFOBJ_NODEJS_BUFFER); // [sigBuffer][func][signer/this][bufView]
if (duk_pcall_method(data->ctx, 1) != 0) { ILibDuktape_Process_UncaughtException(data->ctx); } // ...
}
duk_pop(data->ctx); // ...
@@ -363,29 +348,23 @@ void ILibDuktape_MD5_End(struct ILibDuktape_WritableStream *stream, void *user)
data->buffer[32] = 0;
MD5_Final((unsigned char*)data->buffer, &(data->mctx));
if (data->ctx != NULL && data->OnHash != NULL)
duk_push_external_buffer(data->ctx); // [extBuffer]
duk_config_buffer(data->ctx, -1, data->buffer, 32);
ILibDuktape_EventEmitter_SetupEmit(data->ctx, data->object, "hash"); // [extBuffer][emit][this]["hash"]
duk_push_buffer_object(data->ctx, -4, 0, 32, DUK_BUFOBJ_NODEJS_BUFFER); // [extBuffer][emit][this]["hash"][buffer]
if (duk_pcall_method(data->ctx, 2) != 0) // [retVal]
{
duk_push_heapptr(data->ctx, data->OnHash); // [func]
duk_push_heapptr(data->ctx, data->object); // [func][this]
duk_push_external_buffer(data->ctx); // [func][this][hash]
duk_config_buffer(data->ctx, -1, data->buffer, 32);
if (duk_pcall_method(data->ctx, 1) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(data->ctx);
}
duk_pop(data->ctx); // ...
ILibDuktape_Process_UncaughtException(data->ctx);
}
if (data->ctx != NULL && data->OnHashString != NULL)
duk_pop_2(data->ctx); // ...
ILibDuktape_EventEmitter_SetupEmit(data->ctx, data->object, "hashString"); // [emit][this]["hashString"]
duk_push_string(data->ctx, util_tohex(data->buffer, 32, ILibScratchPad)); // [emit][this]["hashString"][hashString]
if (duk_pcall_method(data->ctx, 2) != 0) // [retVal]
{
duk_push_heapptr(data->ctx, data->OnHashString); // [func]
duk_push_heapptr(data->ctx, data->object); // [func][this]
duk_push_string(data->ctx, util_tohex(data->buffer, 32, ILibScratchPad)); // [func][this][hashString]
if (duk_pcall_method(data->ctx, 1) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(data->ctx);
}
duk_pop(data->ctx); // ...
ILibDuktape_Process_UncaughtException(data->ctx);
}
duk_pop(data->ctx); // ...
}
duk_ret_t ILibDuktape_MD5_syncHash(duk_context *ctx)
{
@@ -431,8 +410,8 @@ duk_ret_t ILibDuktape_MD5_Create(duk_context *ctx)
ILibDuktape_CreateInstanceMethodWithBooleanProperty(ctx, "strRet", 0, "syncHash", ILibDuktape_MD5_syncHash, 1);
ILibDuktape_CreateInstanceMethodWithBooleanProperty(ctx, "strRet", 1, "syncHashString", ILibDuktape_MD5_syncHash, 1);
ILibDuktape_EventEmitter_CreateEvent(emitter, "hash", &(data->OnHash));
ILibDuktape_EventEmitter_CreateEvent(emitter, "hashString", &(data->OnHashString));
ILibDuktape_EventEmitter_CreateEventEx(emitter, "hash");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "hashString");
data->ctx = ctx;
data->object = duk_get_heapptr(ctx, -1);
@@ -457,8 +436,8 @@ duk_ret_t ILibDuktape_SHA256_Create(duk_context *ctx)
ILibDuktape_CreateInstanceMethodWithBooleanProperty(ctx, "strRet", 0, "syncHash", ILibDuktape_SHA256_syncHash, 1);
ILibDuktape_CreateInstanceMethodWithBooleanProperty(ctx, "strRet", 1, "syncHashString", ILibDuktape_SHA256_syncHash, 1);
ILibDuktape_EventEmitter_CreateEvent(emitter, "hash", &(data->OnHash));
ILibDuktape_EventEmitter_CreateEvent(emitter, "hashString", &(data->OnHashString));
ILibDuktape_EventEmitter_CreateEventEx(emitter, "hash");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "hashString");
data->ctx = ctx;
data->object = duk_get_heapptr(ctx, -1);
@@ -474,6 +453,7 @@ duk_ret_t ILibDuktape_SHA384_Create(duk_context *ctx)
ILibDuktape_EventEmitter *emitter;
duk_push_object(ctx); // [sha]
ILibDuktape_WriteID(ctx, "SHA384Stream");
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_SHA512_Data)); // [sha][buffer]
data = (ILibDuktape_SHA512_Data*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, ILibDuktape_SHA512_PTR); // [sha]
@@ -484,8 +464,8 @@ duk_ret_t ILibDuktape_SHA384_Create(duk_context *ctx)
ILibDuktape_CreateInstanceMethodWithBooleanProperty(ctx, "strRet", 0, "syncHash", ILibDuktape_SHA384_syncHash, 1);
ILibDuktape_CreateInstanceMethodWithBooleanProperty(ctx, "strRet", 1, "syncHashString", ILibDuktape_SHA384_syncHash, 1);
ILibDuktape_EventEmitter_CreateEvent(emitter, "hash", &(data->OnHash));
ILibDuktape_EventEmitter_CreateEvent(emitter, "hashString", &(data->OnHashString));
ILibDuktape_EventEmitter_CreateEventEx(emitter, "hash");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "hashString");
data->ctx = ctx;
data->object = duk_get_heapptr(ctx, -1);

View File

@@ -1,3 +1,19 @@
/*
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef ___DUKTAPE_SHA256___
#define ___DUKTAPE_SHA256___

View File

@@ -1,11 +1,11 @@
/*
Copyright 2006 - 2017 Intel Corporation
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
#ifdef WIN32
#include <WinSock2.h>
#include <ws2tcpip.h>
@@ -52,6 +51,7 @@ limitations under the License.
#include "ILibDuktape_Polyfills.h"
#include "ILibDuktape_SimpleDataStore.h"
#include "ILibDuktape_NetworkMonitor.h"
#include "ILibDuktape_ReadableStream.h"
#include "ILibDuktape_SHA256.h"
#include "ILibDuktape_EncryptionStream.h"
@@ -62,13 +62,16 @@ limitations under the License.
extern char **environ;
#endif
#define SCRIPT_ENGINE_PIPE_BUFFER_SIZE 65535
char exeJavaScriptGuid[] = "B996015880544A19B7F7E9BE44914C18";
#define ILibDuktape_ScriptContainer_MasterPtr "\xFF_ScriptContainer_MasterPtr"
#define ILibDuktape_ScriptContainer_SlavePtr "\xFF_ScriptContainer_SlavePtr"
#define ILibDuktape_ScriptContainer_ExePath "\xFF_ScriptContainer_ExePath"
#define ILibDuktape_ScriptContainer_PipeManager "\xFF_ScriptContainer_PipeManager"
#define ILibDuktape_ScriptContainer_PtrTable "\xFF_ScriptContainer_PtrTable"
#define ILibDuktape_ScriptContainer_PtrTable_Idx "\xFF_ScriptContainer_PtrTableIdx"
#define ILibDuktape_ScriptContainer_ProcessIsolated "\xFF_ScriptContainer_ProcessIsolated"
#define ILibDuktape_ScriptContainer_PeerThread "\xFF_ScriptContainer_PeerThread"
#define ILibDuktape_ScriptContainer_Command_Execute_Status "ScriptContainer_Command_Execute_Status"
#define ILibDuktape_ScriptContainer_Command_Log "ScriptContainer_Command_Log"
@@ -79,6 +82,7 @@ extern char **environ;
#define ILibDuktape_ScriptContainer_Settings_ExitUser "\xFF_ScriptContainerSettings_ExitUser"
#define ILibDuktape_ScriptContainer_Process_ArgArray "\xFF_argArray"
#define ILibDuktape_ScriptContainer_Process_Restart "\xFF_ScriptContainer_Process_Restart"
#define ILibDuktape_ScriptContainer_Process_stdin "\xFF_stdin"
#define ILibDuktape_ScriptContainer_ExitCode "\xFF_ExitCode"
#define ILibDuktape_ScriptContainer_Exitting "\xFF_Exiting"
@@ -111,6 +115,7 @@ extern char **environ;
extern void ILibDuktape_MemoryStream_Init(duk_context *ctx);
extern void ILibDuktape_NetworkMonitor_Init(duk_context *ctx);
char g_AgentCrashID[280];
typedef enum SCRIPT_ENGINE_COMMAND
{
@@ -121,6 +126,8 @@ typedef enum SCRIPT_ENGINE_COMMAND
SCRIPT_ENGINE_COMMAND_SEND_JSON = 0x10,
SCRIPT_ENGINE_COMMAND_QUERY = 0x20,
SCRIPT_ENGINE_COMMAND_SET = 0x21,
SCRIPT_ENGINE_COMMAND_ERROR = 0x40,
SCRIPT_ENGINE_COMMAND_EXIT = 0x80,
SCRIPT_ENGINE_COMMAND_LOG = 0xFF
}SCRIPT_ENGINE_COMMAND;
@@ -132,7 +139,8 @@ typedef struct ILibDuktape_ScriptContainer_Master
ILibProcessPipe_Process child;
void *chain;
void *OnExit, *OnError, *OnJSON;
void *PeerThread, *PeerChain;
unsigned int ChildSecurityFlags;
}ILibDuktape_ScriptContainer_Master;
typedef struct ILibDuktape_ScriptContainer_Slave
@@ -140,11 +148,21 @@ typedef struct ILibDuktape_ScriptContainer_Slave
duk_context *ctx;
ILibDuktape_EventEmitter *emitter;
void *OnData;
void *chain;
int exitCode;
int noRespond;
}ILibDuktape_ScriptContainer_Slave;
typedef struct ILibDuktape_ScriptContainer_NonIsolated_Command
{
union { ILibDuktape_ScriptContainer_Master * master; ILibDuktape_ScriptContainer_Slave *slave; }container;
char json[];
}ILibDuktape_ScriptContainer_NonIsolated_Command;
void ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsSlave(void *chain, void *user);
void ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsMaster(void *chain, void *user);
#ifdef _REMOTELOGGING
void ILibDuktape_ScriptContainer_Slave_LogForwarder(ILibRemoteLogging sender, ILibRemoteLogging_Modules module, ILibRemoteLogging_Flags flags, char *buffer, int bufferLen)
{
@@ -190,40 +208,134 @@ void ILibDuktape_ScriptContainer_Slave_OnBrokenPipe(ILibProcessPipe_Pipe sender)
void ILibDuktape_ScriptContainer_CheckEmbedded(char **argv, char **script, int *scriptLen)
{
// Check if .JS file is integrated with executable
int i;
FILE *tmpFile;
char *integratedJavaScript = NULL;
int integratedJavaScriptLen = 0;
#ifdef WIN32
if (ILibString_EndsWith(argv[0], -1, ".exe", 4) == 0)
{
i = sprintf_s(g_AgentCrashID, sizeof(g_AgentCrashID), "%s_", argv[0]);
sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "%s.exe", argv[0]);
fopen_s(&tmpFile, ILibScratchPad, "rb");
}
else
{
i = ILibString_LastIndexOf(argv[0], -1, "\\", 1);
if (i > 0)
{
i = sprintf_s(g_AgentCrashID, sizeof(g_AgentCrashID), "%s", argv[0] + i + 1);
g_AgentCrashID[i-4] = '_';
i -= 3;
}
else
{
i = sprintf_s(g_AgentCrashID, sizeof(g_AgentCrashID), "%s", argv[0]);
g_AgentCrashID[i-4] = '_';
i -= 3;
}
fopen_s(&tmpFile, argv[0], "rb");
}
#else
i = sprintf_s(g_AgentCrashID, sizeof(g_AgentCrashID), "%s_", argv[0]);
tmpFile = fopen(argv[0], "rb");
#endif
if (tmpFile != NULL)
{
fseek(tmpFile, 0, SEEK_END);
fseek(tmpFile, ftell(tmpFile) - 4, SEEK_SET);
ignore_result(fread(ILibScratchPad, 1, 4, tmpFile));
fseek(tmpFile, 0, SEEK_END);
if (ftell(tmpFile) == ntohl(((int*)ILibScratchPad)[0]))
SHA512_CTX shctx;
char hashBuffer[4096];
char hashValue[1 + UTIL_SHA384_HASHSIZE];
int hashBufferReadLen;
SHA384_Init(&shctx);
while ((hashBufferReadLen = (int)fread(hashBuffer, 1, sizeof(hashBuffer), tmpFile)) > 0)
{
fseek(tmpFile, ftell(tmpFile) - 8, SEEK_SET);
SHA384_Update(&shctx, hashBuffer, hashBufferReadLen);
}
SHA384_Final((unsigned char*)hashValue, &shctx);
util_tohex(hashValue, UTIL_SHA384_HASHSIZE, g_AgentCrashID + i);
#ifdef WIN32
memcpy_s(g_AgentCrashID + i + 16, 5, ".exe", 5);
#else
g_AgentCrashID[i + 16] = 0;
#endif
g_ILibCrashID = g_AgentCrashID;
#ifdef WIN32
// Read the PE Headers, to determine where to look for the Embedded JS
char *optHeader = NULL;
fseek(tmpFile, 0, SEEK_SET);
ignore_result(fread(ILibScratchPad, 1, 2, tmpFile));
if (ntohs(((unsigned int*)ILibScratchPad)[0]) == 19802) // 5A4D
{
fseek(tmpFile, 60, SEEK_SET);
ignore_result(fread(ILibScratchPad, 1, 4, tmpFile));
integratedJavaScriptLen = ntohl(((int*)ILibScratchPad)[0]);
integratedJavaScript = ILibMemory_Allocate(1 + integratedJavaScriptLen, 0, NULL, NULL);
fseek(tmpFile, 0, SEEK_END);
fseek(tmpFile, ftell(tmpFile) - 8 - integratedJavaScriptLen, SEEK_SET);
fseek(tmpFile, ((unsigned *)ILibScratchPad)[0], SEEK_SET);
ignore_result(fread(ILibScratchPad, 1, 24, tmpFile));
if (((unsigned int*)ILibScratchPad)[0] == 17744)
{
// PE Image
optHeader = ILibMemory_AllocateA(((unsigned short*)ILibScratchPad)[10]);
ignore_result(fread(optHeader, 1, ILibMemory_AllocateA_Size(optHeader), tmpFile));
switch (((unsigned short*)optHeader)[0])
{
case 0x10B:
if (((unsigned int*)(optHeader + 128))[0] != 0)
{
fseek(tmpFile, ((unsigned int*)(optHeader + 128))[0] - 16, SEEK_SET);
}
else
{
fseek(tmpFile, -16, SEEK_END);
}
break;
case 0x20B:
if (((unsigned int*)(optHeader + 144))[0] != 0)
{
fseek(tmpFile, ((unsigned int*)(optHeader + 144))[0] - 16, SEEK_SET);
}
else
{
fseek(tmpFile, -16, SEEK_END);
}
break;
default:
fclose(tmpFile);
return;
}
ignore_result(fread(ILibScratchPad, 1, 16, tmpFile));
util_hexToBuf(exeJavaScriptGuid, 32, ILibScratchPad2);
if (memcmp(ILibScratchPad, ILibScratchPad2, 16) == 0)
{
// Found an Embedded JS
fseek(tmpFile, -20, SEEK_CUR);
ignore_result(fread((void*)&integratedJavaScriptLen, 1, 4, tmpFile));
integratedJavaScriptLen = (int)ntohl(integratedJavaScriptLen);
fseek(tmpFile, -4 - integratedJavaScriptLen, SEEK_CUR);
integratedJavaScript = ILibMemory_Allocate(integratedJavaScriptLen + 1, 0, NULL, NULL);
ignore_result(fread(integratedJavaScript, 1, integratedJavaScriptLen, tmpFile));
integratedJavaScript[integratedJavaScriptLen] = 0;
}
}
}
#else
fseek(tmpFile, -16, SEEK_END);
ignore_result(fread(ILibScratchPad, 1, 16, tmpFile));
util_hexToBuf(exeJavaScriptGuid, 32, ILibScratchPad2);
if (memcmp(ILibScratchPad, ILibScratchPad2, 16) == 0)
{
// Found an Embedded JS
fseek(tmpFile, -20, SEEK_CUR);
ignore_result(fread((void*)&integratedJavaScriptLen, 1, 4, tmpFile));
integratedJavaScriptLen = (int)ntohl(integratedJavaScriptLen);
fseek(tmpFile, -4 - integratedJavaScriptLen, SEEK_CUR);
integratedJavaScript = ILibMemory_Allocate(integratedJavaScriptLen + 1, 0, NULL, NULL);
ignore_result(fread(integratedJavaScript, 1, integratedJavaScriptLen, tmpFile));
integratedJavaScript[integratedJavaScriptLen] = 0;
}
#endif
fclose(tmpFile);
}
*script = integratedJavaScript;
@@ -353,6 +465,146 @@ duk_ret_t ILibDuktape_ScriptContainer_Process_env(duk_context *ctx)
return(1);
}
duk_ret_t ILibDuktape_ScriptContainer_Process_Finalizer(duk_context *ctx)
{
// We need to dispatch the 'exit' event
int exitCode = 0;
duk_push_this(ctx); // [process]
if (duk_has_prop_string(ctx, -1, "\xFF_ExitCode"))
{
duk_get_prop_string(ctx, -1, "\xFF_ExitCode"); // [process][exitCode]
exitCode = duk_get_int(ctx, -1);
duk_pop(ctx); // [process]
}
ILibDuktape_EventEmitter_SetupEmit(ctx, duk_get_heapptr(ctx, -1), "exit"); // [emit][this]['exit']
duk_push_int(ctx, exitCode); // [emit][this]['exit'][exitCode]
duk_call_method(ctx, 2);
return(0);
}
typedef struct ILibDuktape_Process_StdIn_Data
{
ILibDuktape_readableStream *rs;
#ifdef WIN32
HANDLE workerThread;
HANDLE resumeEvent;
int exit;
#endif
int wasUnshifted;
int endPointer;
int bufferSize;
char buffer[];
}ILibDuktape_Process_StdIn_Data;
#ifdef WIN32
void __stdcall ILibDuktape_Process_stdin_readSink(ULONG_PTR obj)
{
ILibDuktape_Process_StdIn_Data *data = (ILibDuktape_Process_StdIn_Data*)obj;
int endPointer;
do
{
endPointer = data->endPointer;
data->wasUnshifted = 0;
ILibDuktape_readableStream_WriteData(data->rs, data->buffer, data->endPointer);
} while (!data->rs->paused && data->wasUnshifted > 0 && data->wasUnshifted != endPointer);
data->endPointer = data->wasUnshifted;
if (!data->rs->paused) { SetEvent(data->resumeEvent); }
}
#endif
void ILibDuktape_Process_stdin_pauseSink(struct ILibDuktape_readableStream *sender, void *user)
{
UNREFERENCED_PARAMETER(sender);
UNREFERENCED_PARAMETER(user);
// NO-OP, because stream state flag will be paused, which will cause the processing loop to exit
}
void ILibDuktape_Process_stdin_resumeSink(struct ILibDuktape_readableStream *sender, void *user)
{
ILibDuktape_Process_StdIn_Data *data = (ILibDuktape_Process_StdIn_Data*)user;
#ifdef WIN32
SetEvent(data->resumeEvent);
#endif
}
int ILibDuktape_Process_stdin_unshiftSink(struct ILibDuktape_readableStream *sender, int unshiftBytes, void *user)
{
ILibDuktape_Process_StdIn_Data *data = (ILibDuktape_Process_StdIn_Data*)user;
data->wasUnshifted = unshiftBytes <= data->endPointer ? unshiftBytes : data->endPointer;
if (unshiftBytes > 0 && unshiftBytes < data->endPointer)
{
memmove_s(data->buffer, data->bufferSize, data->buffer + (data->endPointer - unshiftBytes), unshiftBytes);
data->endPointer = unshiftBytes;
}
return(data->wasUnshifted);
}
#ifdef WIN32
void ILibDuktape_Process_stdin_WindowsRunLoop(void *arg)
{
ILibDuktape_Process_StdIn_Data *data = (ILibDuktape_Process_StdIn_Data*)arg;
HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
DWORD bytesRead, waitResult;
while (((waitResult = WaitForSingleObjectEx(data->resumeEvent, INFINITE, TRUE)) == WAIT_OBJECT_0 || waitResult == WAIT_IO_COMPLETION) && !data->exit)
{
if (!ReadFile(h, data->buffer + data->endPointer, data->bufferSize - data->endPointer, &bytesRead, NULL))
{
break;
}
else
{
ResetEvent(data->resumeEvent); // Reset, becuase we'll need to pause and context switch to Duktape thread
data->endPointer += (int)bytesRead;
QueueUserAPC((PAPCFUNC)ILibDuktape_Process_stdin_readSink, ILibChain_GetMicrostackThreadHandle(data->rs->chain), (ULONG_PTR)data);
}
}
}
#endif
duk_ret_t ILibDuktape_Process_stdin_finalizer(duk_context *ctx)
{
duk_get_prop_string(ctx, 0, ILibDuktape_readableStream_RSPTRS);
ILibDuktape_readableStream *rs = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
ILibDuktape_Process_StdIn_Data *data = (ILibDuktape_Process_StdIn_Data*)rs->user;
#ifdef WIN32
data->exit = 1;
SetEvent(data->resumeEvent);
CancelSynchronousIo(data->workerThread);
WaitForSingleObject(data->workerThread, 10000);
CloseHandle(data->resumeEvent);
#endif
free(data);
return(0);
}
duk_ret_t ILibDuktape_Process_stdin_get(duk_context *ctx)
{
duk_push_this(ctx); // [process]
if (duk_has_prop_string(ctx, -1, ILibDuktape_ScriptContainer_Process_stdin))
{
duk_get_prop_string(ctx, -1, ILibDuktape_ScriptContainer_Process_stdin);
return(1);
}
duk_push_object(ctx); // [process][stdin]
duk_dup(ctx, -1); // [process][stdin][dup]
duk_put_prop_string(ctx, -3, ILibDuktape_ScriptContainer_Process_stdin); // [process][stdin]
ILibDuktape_WriteID(ctx, "process.stdin");
ILibDuktape_readableStream *rs = ILibDuktape_ReadableStream_InitEx(ctx, ILibDuktape_Process_stdin_pauseSink, ILibDuktape_Process_stdin_resumeSink, ILibDuktape_Process_stdin_unshiftSink, NULL);
rs->user = ILibMemory_Allocate(sizeof(ILibDuktape_Process_StdIn_Data) + 4096, 0, NULL, NULL);
((ILibDuktape_Process_StdIn_Data*)rs->user)->rs = rs;
((ILibDuktape_Process_StdIn_Data*)rs->user)->bufferSize = 4096;
#ifdef WIN32
((ILibDuktape_Process_StdIn_Data*)rs->user)->resumeEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
((ILibDuktape_Process_StdIn_Data*)rs->user)->workerThread = ILibSpawnNormalThread(ILibDuktape_Process_stdin_WindowsRunLoop, rs->user);
#endif
ILibDuktape_EventEmitter_AddOnEx(ctx, -1, "~", ILibDuktape_Process_stdin_finalizer);
return(1);
}
void ILibDuktape_ScriptContainer_Process_Init(duk_context *ctx, char **argList)
{
int i = 0;
@@ -360,6 +612,7 @@ void ILibDuktape_ScriptContainer_Process_Init(duk_context *ctx, char **argList)
duk_push_global_object(ctx); // [g]
duk_push_object(ctx); // [g][process]
ILibDuktape_WriteID(ctx, "process");
ILibDuktape_CreateEventWithGetter(ctx, "env", ILibDuktape_ScriptContainer_Process_env);
#if defined(WIN32) // [g][process][platform]
@@ -416,8 +669,21 @@ void ILibDuktape_ScriptContainer_Process_Init(duk_context *ctx, char **argList)
duk_push_int(ctx, 0);
ILibDuktape_CreateEventWithGetterAndCustomProperty(ctx, "readOnly", "_argv", ILibDuktape_ScriptContainer_Process_Argv);
duk_push_heap_stash(ctx); // [g][process][stash]
if (!duk_has_prop_string(ctx, -1, ILibDuktape_ScriptContainer_SlavePtr))
{
duk_pop(ctx); // [g][process]
ILibDuktape_CreateEventWithGetter(ctx, "stdin", ILibDuktape_Process_stdin_get);
}
else
{
duk_pop(ctx); // [g][process]
}
duk_put_prop_string(ctx, -2, "process"); // [g]
duk_pop(ctx); // ...
ILibDuktape_EventEmitter_AddOnceEx(emitter, "~", ILibDuktape_ScriptContainer_Process_Finalizer, 1);
}
void ILibDuktape_ScriptContainer_ExecTimeout_Finalizer(duk_context *ctx, void *timeoutKey)
{
@@ -510,9 +776,9 @@ void ILibDuktape_ScriptContainer_Engine_free(void *udata, void *ptr)
{
free(ptr);
}
void ILibDuktape_ScriptContainer_Engine_fatal(duk_context *ctx, duk_errcode_t code, const char *msg)
void ILibDuktape_ScriptContainer_Engine_fatal(void *udata, const char *msg)
{
ILIBCRITICALEXITMSG(code, msg);
ILIBCRITICALEXITMSG(254, msg);
}
duk_ret_t ILibDuktape_ScriptContainer_OS_arch(duk_context *ctx)
{
@@ -756,6 +1022,7 @@ duk_ret_t ILibDuktape_ScriptContainer_OS_networkInterfaces(duk_context *ctx)
void ILibDuktape_ScriptContainer_OS_Push(duk_context *ctx, void *chain)
{
duk_push_object(ctx); // [os]
ILibDuktape_WriteID(ctx, "os");
#ifdef WIN32
duk_push_string(ctx, "\r\n");
@@ -773,10 +1040,13 @@ 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 *ILibDuktape_ScriptContainer_InitializeJavaScriptEngine_minimal()
{
duk_context *ctx = duk_create_heap(ILibDuktape_ScriptContainer_Engine_malloc, ILibDuktape_ScriptContainer_Engine_realloc, ILibDuktape_ScriptContainer_Engine_free, NULL, ILibDuktape_ScriptContainer_Engine_fatal);
//duk_context *ctx = duk_create_heap_default();
return(ctx);
}
duk_context *ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx3(duk_context *ctx, SCRIPT_ENGINE_SECURITY_FLAGS securityFlags, unsigned int executionTimeout, void *chain, char **argList, ILibSimpleDataStore *db, char *exePath, ILibProcessPipe_Manager pipeManager, ILibDuktape_HelperEvent exitHandler, void *exitUser)
{
void **timeoutKey = executionTimeout > 0 ? (void**)ILibMemory_Allocate(sizeof(void*), 0, NULL, NULL) : NULL;
duk_push_heap_stash(ctx); // [s]
@@ -897,7 +1167,7 @@ int ILibDuktape_ScriptContainer_CompileJavaScript_FromFile(duk_context *ctx, cha
if (path == NULL || pathLen == 0)
{
duk_push_error_object(ctx, DUK_ERR_API_ERROR, "Invalid Path specified");
duk_push_error_object(ctx, DUK_ERR_ERROR, "Invalid Path specified");
return(1);
}
else
@@ -1153,16 +1423,15 @@ void ILibDuktape_ScriptContainer_Slave_ProcessCommands(ILibDuktape_ScriptContain
break;
case SCRIPT_ENGINE_COMMAND_SEND_JSON:
{
if (slave->OnData != NULL)
if (ILibDuktape_EventEmitter_HasListeners(slave->emitter, "data")!=0)
{
char *json = Duktape_GetStringPropertyValue(slave->ctx, -1, "json", NULL);
if (json != NULL)
{
duk_push_heapptr(slave->ctx, slave->OnData); // [func]
duk_push_heapptr(slave->ctx, slave->emitter->object); // [func][this]
duk_push_string(slave->ctx, json); // [func][this][json]
duk_json_decode(slave->ctx, -1); // [func][this][object]
if (duk_pcall_method(slave->ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(slave->ctx, "ScriptContainer.OnData(): "); }
ILibDuktape_EventEmitter_SetupEmit(slave->ctx, slave->emitter->object, "data"); // [emit][this][data]
duk_push_string(slave->ctx, json); // [emit][this][data][json]
duk_json_decode(slave->ctx, -1); // [emit][this][data][object]
if (duk_pcall_method(slave->ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(slave->ctx, "ScriptContainer.OnData(): "); }
duk_pop(slave->ctx); // ...
}
}
@@ -1313,6 +1582,15 @@ duk_ret_t ILibDuktape_ScriptContainer_Exit(duk_context *ctx)
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, ILibDuktape_ScriptContainer_MasterPtr);
master = (ILibDuktape_ScriptContainer_Master*)Duktape_GetBuffer(ctx, -1, NULL);
if (master->PeerChain != NULL)
{
char json[] = "{\"command\": \"128\"}";
ILibDuktape_ScriptContainer_NonIsolated_Command *cmd = ILibMemory_Allocate(sizeof(json) + sizeof(ILibDuktape_ScriptContainer_NonIsolated_Command), 0, NULL, NULL);
cmd->container.slave = ((void**)ILibMemory_GetExtraMemory(master->PeerChain, ILibMemory_CHAIN_CONTAINERSIZE))[1];
memcpy_s(cmd->json, sizeof(json), json, sizeof(json));
ILibChain_RunOnMicrostackThread(master->PeerChain, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsSlave, cmd);
return(0);
}
if (ILibIsChainBeingDestroyed(Duktape_GetChain(ctx)) == 0)
{
@@ -1338,6 +1616,27 @@ duk_ret_t ILibDuktape_ScriptContainer_ExecuteString(duk_context *ctx)
duk_get_prop_string(ctx, -1, ILibDuktape_ScriptContainer_MasterPtr); // [container][buffer]
master = (ILibDuktape_ScriptContainer_Master*)Duktape_GetBuffer(ctx, -1, NULL); // [container][buffer]
if (master->PeerChain != NULL)
{
char json[] = "{\"command\": \"2\", \"base64\": \"\"}";
char *payload;
duk_size_t payloadLen;
payload = (char*)duk_get_lstring(ctx, 0, &payloadLen);
int encodedPayloadLen = ILibBase64EncodeLength((int)payloadLen);
ILibDuktape_ScriptContainer_NonIsolated_Command *cmd = (ILibDuktape_ScriptContainer_NonIsolated_Command*)ILibMemory_Allocate(sizeof(ILibDuktape_ScriptContainer_NonIsolated_Command) + encodedPayloadLen + sizeof(json), 0, NULL, NULL);
cmd->container.slave = (ILibDuktape_ScriptContainer_Slave*)((void**)ILibMemory_GetExtraMemory(master->PeerChain, ILibMemory_CHAIN_CONTAINERSIZE))[1];
int i = sprintf_s(cmd->json, sizeof(json) + encodedPayloadLen, json);
char *output = cmd->json + i -2;
i += ILibBase64Encode((unsigned char*)payload, (int)payloadLen, (unsigned char**)&output);
sprintf_s(cmd->json + i - 2, 3, "\"}");
ILibChain_RunOnMicrostackThread(master->PeerChain, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsSlave, cmd);
return(0);
}
if (ptr != NULL) { seq = ILibDuktape_ScriptContainer_AddVoidPtr(ctx, duk_get_heapptr(ctx, -2), ptr); }
duk_push_object(ctx); // [container][buffer][obj]
@@ -1364,18 +1663,13 @@ duk_ret_t ILibDuktape_ScriptContainer_ExecuteString(duk_context *ctx)
void ILibDuktape_ScriptContainer_ExitSink(ILibProcessPipe_Process sender, int exitCode, void* user)
{
ILibDuktape_ScriptContainer_Master *master = (ILibDuktape_ScriptContainer_Master*)user;
if (master->OnExit != NULL)
ILibDuktape_EventEmitter_SetupEmit(master->ctx, master->emitter->object, "exit"); // [emit][this][exit]
duk_push_int(master->ctx, exitCode); // [emit][this][exit][code]
if (duk_pcall_method(master->ctx, 2) != 0)
{
duk_push_heapptr(master->ctx, master->OnExit); // [func]
duk_push_heapptr(master->ctx, master->emitter->object); // [func][this]
duk_push_int(master->ctx, exitCode); // [func][this][code]
if (duk_pcall_method(master->ctx, 1) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(master->ctx);
}
duk_pop(master->ctx); // ...
ILibDuktape_Process_UncaughtException(master->ctx);
}
duk_pop(master->ctx);
master->child = NULL;
}
@@ -1402,16 +1696,15 @@ void ILibDuktape_ScriptContainer_StdErrSink_MicrostackThread(void *chain, void *
{
case SCRIPT_ENGINE_COMMAND_SEND_JSON:
{
if (master->OnJSON != NULL)
{
if(ILibDuktape_EventEmitter_HasListeners(master->emitter, "data")!=0)
{
char *json = Duktape_GetStringPropertyValue(master->ctx, -1, "json", NULL);
if (json != NULL)
{
duk_push_heapptr(master->ctx, master->OnJSON);
duk_push_heapptr(master->ctx, master->emitter->object);
duk_push_string(master->ctx, json);
duk_json_decode(master->ctx, -1);
if (duk_pcall_method(master->ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(master->ctx, "ScriptContainer.OnData(): "); }
ILibDuktape_EventEmitter_SetupEmit(master->ctx, master->emitter->object, "data"); // [emit][this][data]
duk_push_string(master->ctx, json); // [emit][this][data][str]
duk_json_decode(master->ctx, -1); // [emit][this][data][json]
if (duk_pcall_method(master->ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(master->ctx, "ScriptContainer.OnData(): "); }
duk_pop(master->ctx);
}
}
@@ -1430,14 +1723,10 @@ void ILibDuktape_ScriptContainer_StdErrSink_MicrostackThread(void *chain, void *
if ((i = Duktape_GetIntPropertyValue(master->ctx, -1, "sequence", -1)) < 0)
{
// No callback was specified
if (master->OnError != NULL)
{
duk_push_heapptr(master->ctx, master->OnError); // [func]
duk_push_heapptr(master->ctx, master->emitter->object); // [func][this]
duk_get_prop_string(master->ctx, -3, "error"); // [func][this][error]
if (duk_pcall_method(master->ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(master->ctx, "ScriptContainer_OnError_Dispatch(): "); }
duk_pop(master->ctx); // ...
}
ILibDuktape_EventEmitter_SetupEmit(master->ctx, master->emitter->object, "error"); // [emit][this][error]
duk_get_prop_string(master->ctx, -4, "error"); // [emit][this][error][errorObj]
if (duk_pcall_method(master->ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(master->ctx, "ScriptContainer_OnError_Dispatch(): "); }
duk_pop(master->ctx); // ...
}
else
{
@@ -1515,6 +1804,17 @@ duk_ret_t ILibDuktape_ScriptContainer_Finalizer(duk_context *ctx)
{
ILibProcessPipe_Process_KillEx(master->child);
}
else if (master->PeerChain != NULL)
{
char json[] = "{\"command\": \"128\", \"noResponse\": \"1\"}";
ILibDuktape_ScriptContainer_NonIsolated_Command *cmd = ILibMemory_Allocate(sizeof(json) + sizeof(ILibDuktape_ScriptContainer_NonIsolated_Command), 0, NULL, NULL);
cmd->container.slave = ((void**)ILibMemory_GetExtraMemory(master->PeerChain, ILibMemory_CHAIN_CONTAINERSIZE))[1];
memcpy_s(cmd->json, sizeof(json), json, sizeof(json));
ILibChain_RunOnMicrostackThread(master->PeerChain, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsSlave, cmd);
#ifdef WIN32
WaitForSingleObject(master->PeerThread, INFINITE);
#endif
}
return(0);
}
@@ -1535,10 +1835,23 @@ duk_ret_t ILibDuktape_ScriptContainer_SendToSlave(duk_context *ctx)
duk_put_prop_string(ctx, -2, "json"); // [container][master][obj]
duk_json_encode(ctx, -1); // [container][master][json]
len = sprintf_s(ILibScratchPad2 + 4, sizeof(ILibScratchPad2) - 4, "%s", duk_get_string(ctx, -1));
((int*)ILibScratchPad2)[0] = len + 4;
ILibProcessPipe_Process_WriteStdIn(master->child, ILibScratchPad2, len + 4, ILibTransport_MemoryOwnership_USER);
if (master->child != NULL)
{
len = sprintf_s(ILibScratchPad2 + 4, sizeof(ILibScratchPad2) - 4, "%s", duk_get_string(ctx, -1));
((int*)ILibScratchPad2)[0] = len + 4;
ILibProcessPipe_Process_WriteStdIn(master->child, ILibScratchPad2, len + 4, ILibTransport_MemoryOwnership_USER);
}
else if(master->PeerChain != NULL)
{
duk_size_t payloadLen;
char *payload = (char*)duk_get_lstring(ctx, -1, &payloadLen);
ILibDuktape_ScriptContainer_NonIsolated_Command *cmd = ILibMemory_Allocate(sizeof(ILibDuktape_ScriptContainer_NonIsolated_Command) + (int)payloadLen + 1, 0, NULL, NULL);
cmd->container.slave = (ILibDuktape_ScriptContainer_Slave*)((void**)ILibMemory_GetExtraMemory(master->PeerChain, ILibMemory_CHAIN_CONTAINERSIZE))[1];
memcpy_s(cmd->json, payloadLen + 1, payload, payloadLen + 1);
ILibChain_RunOnMicrostackThread(master->PeerChain, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsSlave, cmd);
}
return(0);
}
duk_ret_t ILibDuktape_ScriptContainer_Master_AddModule(duk_context *ctx)
@@ -1565,6 +1878,181 @@ duk_ret_t ILibDuktape_ScriptContainer_Master_AddModule(duk_context *ctx)
ILibProcessPipe_Process_WriteStdIn(master->child, ILibScratchPad2, len+4, ILibTransport_MemoryOwnership_USER);
return(0);
}
void ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsMaster(void *chain, void *user)
{
ILibDuktape_ScriptContainer_NonIsolated_Command *cmd = (ILibDuktape_ScriptContainer_NonIsolated_Command*)user;
ILibDuktape_ScriptContainer_Master *master = cmd->container.master;
ILibDuktape_ScriptContainer_Slave *slave = master->PeerChain == NULL ? NULL : (ILibDuktape_ScriptContainer_Slave*)((void**)ILibMemory_GetExtraMemory(master->PeerChain, ILibMemory_CHAIN_CONTAINERSIZE))[1];
int id;
duk_push_string(master->ctx, cmd->json); // [string]
duk_json_decode(master->ctx, -1); // [json]
free(cmd);
switch ((id = Duktape_GetIntPropertyValue(master->ctx, -1, "command", -1)))
{
case 0: // Ready
{
// Call INIT first
char json[] = "{\"command\": \"1\"}";
ILibDuktape_ScriptContainer_NonIsolated_Command* initCmd = (ILibDuktape_ScriptContainer_NonIsolated_Command*)ILibMemory_Allocate(sizeof(json) + sizeof(ILibDuktape_ScriptContainer_NonIsolated_Command), 0, NULL, NULL);
initCmd->container.slave = slave;
memcpy_s(initCmd->json, sizeof(json), json, sizeof(json));
ILibChain_RunOnMicrostackThread(master->PeerChain, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsSlave, initCmd);
// Emit Ready Event
duk_push_heapptr(master->ctx, master->emitter->object); // [json][container]
duk_get_prop_string(master->ctx, -1, "emit"); // [json][container][emit]
duk_swap_top(master->ctx, -2); // [json][emit][this]
duk_push_string(master->ctx, "ready"); // [json][emit][this][ready]
if (duk_pcall_method(master->ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(master->ctx, "Error Dispatching 'ready' event to Master Script Container"); }
duk_pop(master->ctx); // [json]
}
break;
case SCRIPT_ENGINE_COMMAND_ERROR:
duk_push_heapptr(master->ctx, master->emitter->object); // [json][container]
duk_get_prop_string(master->ctx, -1, "emit"); // [json][container][emit]
duk_swap_top(master->ctx, -2); // [json][emit][this]
duk_push_string(master->ctx, "error"); // [json][emit][this][error]
duk_get_prop_string(master->ctx, -4, "message"); // [json][emit][this][error][msg]
if (duk_pcall_method(master->ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(master->ctx, "Error Emitting ScriptContainer Error Message: "); }
duk_pop(master->ctx); // [json]
break;
case SCRIPT_ENGINE_COMMAND_EXIT:
duk_push_heapptr(master->ctx, master->emitter->object); // [json][container]
duk_get_prop_string(master->ctx, -1, "emit"); // [json][container][emit]
duk_swap_top(master->ctx, -2); // [json][emit][this]
duk_push_string(master->ctx, "exit"); // [json][emit][this][exit]
duk_get_prop_string(master->ctx, -4, "exitCode"); // [json][emit][this][exit][msg]
if (duk_pcall_method(master->ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(master->ctx, "Error Emitting ScriptContainer Exit: "); }
duk_pop(master->ctx); // [json]
master->PeerChain = NULL;
break;
default:
ILibDuktape_Process_UncaughtExceptionEx(master->ctx, "Unknown Command [%d] Received from Slave Container ", id);
break;
}
duk_pop(master->ctx); // ...
}
void ILibDuktape_ScriptContainer_NonIsolatedWorker_ExceptionSink(duk_context *ctx, char *msg, void *user)
{
duk_push_object(ctx); // [obj]
duk_push_int(ctx, (int)SCRIPT_ENGINE_COMMAND_ERROR);
duk_put_prop_string(ctx, -2, "command");
duk_push_string(ctx, msg);
duk_put_prop_string(ctx, -2, "message");
duk_json_encode(ctx, -1); // [json]
duk_size_t payloadLen;
char *payload = (char*)duk_get_lstring(ctx, -1, &payloadLen);
ILibDuktape_ScriptContainer_NonIsolated_Command *cmd = (ILibDuktape_ScriptContainer_NonIsolated_Command*)ILibMemory_Allocate((int)(sizeof(ILibDuktape_ScriptContainer_NonIsolated_Command) + payloadLen + 1), 0, NULL, NULL);
cmd->container.master = ((void**)ILibMemory_GetExtraMemory(Duktape_GetChain(ctx), ILibMemory_CHAIN_CONTAINERSIZE))[0];
memcpy_s(cmd->json, payloadLen + 1, payload, payloadLen + 1);
duk_pop(ctx); // ...
ILibChain_RunOnMicrostackThread(cmd->container.master->chain, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsMaster, cmd);
}
void ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsSlave(void *chain, void *user)
{
ILibDuktape_ScriptContainer_NonIsolated_Command *cmd = (ILibDuktape_ScriptContainer_NonIsolated_Command*)user;
ILibDuktape_ScriptContainer_Slave *slave = cmd->container.slave;
ILibDuktape_ScriptContainer_Master *master = (ILibDuktape_ScriptContainer_Master*)((void**)ILibMemory_GetExtraMemory(slave->chain, ILibMemory_CHAIN_CONTAINERSIZE))[0];
int id;
duk_push_string(slave->ctx, cmd->json); // [string]
duk_json_decode(slave->ctx, -1); // [json]
free(cmd);
switch ((id = Duktape_GetIntPropertyValue(slave->ctx, -1, "command", -1)))
{
case SCRIPT_ENGINE_COMMAND_INIT:
ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx3(slave->ctx, (SCRIPT_ENGINE_SECURITY_FLAGS)master->ChildSecurityFlags, 0, slave->chain, NULL, NULL, NULL, NULL, ILibDuktape_ScriptContainer_Slave_HeapDestroyed, slave);
ILibDuktape_SetNativeUncaughtExceptionHandler(slave->ctx, ILibDuktape_ScriptContainer_NonIsolatedWorker_ExceptionSink, master);
break;
case SCRIPT_ENGINE_COMMAND_EXEC:
{
char *payload;
duk_size_t payloadLen;
payload = (char*)Duktape_GetStringPropertyValueEx(slave->ctx, -1, "base64", NULL, &payloadLen);
payloadLen = ILibBase64Decode((unsigned char*)payload, (int)payloadLen, (unsigned char**)&payload);
if (ILibDuktape_ScriptContainer_CompileJavaScript(slave->ctx, payload, (int)payloadLen) == 0 && ILibDuktape_ScriptContainer_ExecuteByteCode(slave->ctx) == 0)
{
// SUCCESS
duk_pop(slave->ctx);
}
else
{
// ERROR
ILibDuktape_Process_UncaughtExceptionEx(slave->ctx, "ScriptContainer Error: ");
duk_pop(slave->ctx);
}
}
break;
case SCRIPT_ENGINE_COMMAND_SEND_JSON:
{
if (slave->emitter != NULL)
{
duk_get_prop_string(slave->ctx, -1, "json"); // [cmd][string]
duk_json_decode(slave->ctx, -1); // [cmd][obj]
duk_push_heapptr(slave->ctx, slave->emitter->object); // [cmd][obj][container]
duk_get_prop_string(slave->ctx, -1, "emit"); // [cmd][obj][container][emit]
duk_swap_top(slave->ctx, -2); // [cmd][obj][emit][this]
duk_push_string(slave->ctx, "data"); // [cmd][obj][emit][this][data]
duk_dup(slave->ctx, -4); // [cmd][obj][emit][this][data][obj]
if (duk_pcall_method(slave->ctx, 2) != 0) { ILibDuktape_Process_UncaughtException(slave->ctx); }
duk_pop_2(slave->ctx); // [cmd]
}
}
break;
case SCRIPT_ENGINE_COMMAND_EXIT:
slave->noRespond = Duktape_GetIntPropertyValue(slave->ctx, -1, "noResponse", 0);
duk_pop(slave->ctx);
duk_destroy_heap(slave->ctx);
return;
}
duk_pop(slave->ctx); // ...
}
void ILibDuktape_ScriptContainer_NonIsolatedWorker(void *arg)
{
ILibDuktape_ScriptContainer_Master *master = (ILibDuktape_ScriptContainer_Master*)arg;
ILibDuktape_ScriptContainer_Slave *slave = ILibMemory_AllocateA(sizeof(ILibDuktape_ScriptContainer_Slave));
char json[] = "{\"command\": \"0\"}";
slave->chain = ILibCreateChainEx(2 * sizeof(void*));
((void**)ILibMemory_GetExtraMemory(slave->chain, ILibMemory_CHAIN_CONTAINERSIZE))[0] = master;
((void**)ILibMemory_GetExtraMemory(slave->chain, ILibMemory_CHAIN_CONTAINERSIZE))[1] = slave;
master->PeerChain = slave->chain;
slave->ctx = ILibDuktape_ScriptContainer_InitializeJavaScriptEngine_minimal();
duk_push_heap_stash(slave->ctx);
duk_push_pointer(slave->ctx, slave);
duk_put_prop_string(slave->ctx, -2, ILibDuktape_ScriptContainer_SlavePtr);
duk_pop(slave->ctx);
ILibDuktape_ScriptContainer_NonIsolated_Command* cmd = (ILibDuktape_ScriptContainer_NonIsolated_Command*)ILibMemory_Allocate(sizeof(json) + sizeof(ILibDuktape_ScriptContainer_NonIsolated_Command), 0, NULL, NULL);
cmd->container.master = master;
memcpy_s(cmd->json, sizeof(json), json, sizeof(json));
ILibChain_RunOnMicrostackThread(master->chain, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsMaster, cmd);
ILibStartChain(slave->chain);
if (slave->noRespond == 0)
{
cmd = (ILibDuktape_ScriptContainer_NonIsolated_Command*)ILibMemory_Allocate(64 + sizeof(ILibDuktape_ScriptContainer_NonIsolated_Command), 0, NULL, NULL);
cmd->container.master = master;
sprintf_s(cmd->json, 64, "{\"command\": \"128\", \"exitCode\": \"%d\"}", slave->exitCode);
ILibChain_RunOnMicrostackThread(master->chain, ILibDuktape_ScriptContainer_NonIsolatedWorker_ProcessAsMaster, cmd);
}
}
duk_ret_t ILibDuktape_ScriptContainer_Create(duk_context *ctx)
{
char *exePath;
@@ -1575,6 +2063,12 @@ duk_ret_t ILibDuktape_ScriptContainer_Create(duk_context *ctx)
char *buffer;
char header[4];
ILibProcessPipe_SpawnTypes spawnType = (duk_get_top(ctx) > 2 && duk_is_number(ctx, 2)) ? (ILibProcessPipe_SpawnTypes)duk_require_int(ctx, 2) : ILibProcessPipe_SpawnTypes_DEFAULT;
int processIsolation = 1;
if (duk_get_top(ctx) > 0 && duk_is_object(ctx, 0))
{
processIsolation = Duktape_GetIntPropertyValue(ctx, 0, "processIsolation", 1);
}
duk_push_heap_stash(ctx);
duk_get_prop_string(ctx, -1, ILibDuktape_ScriptContainer_ExePath);
@@ -1584,6 +2078,7 @@ duk_ret_t ILibDuktape_ScriptContainer_Create(duk_context *ctx)
manager = (ILibProcessPipe_Manager)duk_get_pointer(ctx, -1);
duk_push_object(ctx); // [container]
ILibDuktape_WriteID(ctx, "ScriptContainer.master");
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_ScriptContainer_Master)); // [container][buffer]
master = (ILibDuktape_ScriptContainer_Master*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, ILibDuktape_ScriptContainer_MasterPtr); // [container]
@@ -1592,9 +2087,9 @@ duk_ret_t ILibDuktape_ScriptContainer_Create(duk_context *ctx)
master->ctx = ctx;
master->emitter = ILibDuktape_EventEmitter_Create(ctx);
master->chain = Duktape_GetChain(ctx);
ILibDuktape_EventEmitter_CreateEvent(master->emitter, "exit", &(master->OnExit));
ILibDuktape_EventEmitter_CreateEvent(master->emitter, "error", &(master->OnError));
ILibDuktape_EventEmitter_CreateEvent(master->emitter, "data", &(master->OnJSON));
ILibDuktape_EventEmitter_CreateEventEx(master->emitter, "exit");
ILibDuktape_EventEmitter_CreateEventEx(master->emitter, "error");
ILibDuktape_EventEmitter_CreateEventEx(master->emitter, "data");
ILibDuktape_CreateProperty_InstanceMethod(ctx, "exit", ILibDuktape_ScriptContainer_Exit, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(master->ctx, "ExecuteScript", ILibDuktape_ScriptContainer_ExecuteScript, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(master->ctx, "ExecuteString", ILibDuktape_ScriptContainer_ExecuteString, DUK_VARARGS);
@@ -1602,28 +2097,43 @@ duk_ret_t ILibDuktape_ScriptContainer_Create(duk_context *ctx)
ILibDuktape_CreateInstanceMethod(master->ctx, "addModule", ILibDuktape_ScriptContainer_Master_AddModule, 2);
ILibDuktape_CreateFinalizer(master->ctx, ILibDuktape_ScriptContainer_Finalizer);
unsigned int executionTimeout = (unsigned int)duk_require_int(ctx, 0);
unsigned int securityFlags = (unsigned int)duk_require_int(ctx, 1) | SCRIPT_ENGINE_NO_MESH_AGENT_ACCESS;
if (processIsolation)
{
// We're going to spawn a child process to run this ScriptContainer
unsigned int executionTimeout = (unsigned int)duk_require_int(ctx, 0);
master->ChildSecurityFlags = (unsigned int)duk_require_int(ctx, 1) | SCRIPT_ENGINE_NO_MESH_AGENT_ACCESS;
master->child = ILibProcessPipe_Manager_SpawnProcessEx2(manager, exePath, (char * const*)param, spawnType, 2 * sizeof(void*));
if (master->child == NULL) { return(ILibDuktape_Error(ctx, "ScriptContainer.Create(): Error spawning child process, using [%s]", exePath)); }
master->child = ILibProcessPipe_Manager_SpawnProcessEx2(manager, exePath, (char * const*)param, spawnType, 2 * sizeof(void*));
if (master->child == NULL) { return(ILibDuktape_Error(ctx, "ScriptContainer.Create(): Error spawning child process, using [%s]", exePath)); }
duk_push_true(ctx);
duk_put_prop_string(ctx, -2, ILibDuktape_ScriptContainer_ProcessIsolated);
duk_push_object(ctx); // [container][obj]
duk_push_int(ctx, (int)SCRIPT_ENGINE_COMMAND_INIT);
duk_put_prop_string(ctx, -2, "command");
duk_push_int(ctx, (int)executionTimeout);
duk_put_prop_string(ctx, -2, "executionTimeout");
duk_push_int(ctx, (int)master->ChildSecurityFlags);
duk_put_prop_string(ctx, -2, "securityFlags");
duk_json_encode(ctx, -1);
buffer = (char*)Duktape_GetBuffer(ctx, -1, &bufferLen);
duk_push_object(ctx); // [container][obj]
duk_push_int(ctx, (int)SCRIPT_ENGINE_COMMAND_INIT);
duk_put_prop_string(ctx, -2, "command");
duk_push_int(ctx, (int)executionTimeout);
duk_put_prop_string(ctx, -2, "executionTimeout");
duk_push_int(ctx, (int)securityFlags);
duk_put_prop_string(ctx, -2, "securityFlags");
duk_json_encode(ctx, -1);
buffer = (char*)Duktape_GetBuffer(ctx, -1, &bufferLen);
duk_swap_top(ctx, -2); // [json][container]
duk_swap_top(ctx, -2); // [json][container]
((int*)header)[0] = (int)bufferLen + 4;
ILibProcessPipe_Process_AddHandlers(master->child, SCRIPT_ENGINE_PIPE_BUFFER_SIZE, ILibDuktape_ScriptContainer_ExitSink, ILibDuktape_ScriptContainer_StdOutSink, ILibDuktape_ScriptContainer_StdErrSink, ILibDuktape_ScriptContainer_SendOkSink, master);
ILibProcessPipe_Process_WriteStdIn(master->child, header, sizeof(header), ILibTransport_MemoryOwnership_USER);
ILibProcessPipe_Process_WriteStdIn(master->child, buffer, (int)bufferLen, ILibTransport_MemoryOwnership_USER);
((int*)header)[0] = (int)bufferLen + 4;
ILibProcessPipe_Process_AddHandlers(master->child, SCRIPT_ENGINE_PIPE_BUFFER_SIZE, ILibDuktape_ScriptContainer_ExitSink, ILibDuktape_ScriptContainer_StdOutSink, ILibDuktape_ScriptContainer_StdErrSink, ILibDuktape_ScriptContainer_SendOkSink, master);
ILibProcessPipe_Process_WriteStdIn(master->child, header, sizeof(header), ILibTransport_MemoryOwnership_USER);
ILibProcessPipe_Process_WriteStdIn(master->child, buffer, (int)bufferLen, ILibTransport_MemoryOwnership_USER);
}
else
{
// We're going to spawn a thread to host this Script Container
duk_push_false(ctx);
duk_put_prop_string(ctx, -2, ILibDuktape_ScriptContainer_ProcessIsolated);
ILibDuktape_EventEmitter_CreateEventEx(master->emitter, "ready");
master->PeerThread = ILibSpawnNormalThread(ILibDuktape_ScriptContainer_NonIsolatedWorker, master);
master->ChildSecurityFlags = Duktape_GetIntPropertyValue(ctx, 0, "permissions", 0);
}
return 1;
}
void ILibDuktape_ScriptContainer_PUSH_MASTER(duk_context *ctx, void *chain)
@@ -1653,8 +2163,9 @@ void ILibDuktape_ScriptContainer_PUSH_SLAVE(duk_context *ctx, void *chain)
duk_pop(ctx); // ...
duk_push_object(ctx);
ILibDuktape_WriteID(ctx, "ScriptContainer.slave");
slave->emitter = ILibDuktape_EventEmitter_Create(ctx);
ILibDuktape_EventEmitter_CreateEvent(slave->emitter, "data", &(slave->OnData));
ILibDuktape_EventEmitter_CreateEventEx(slave->emitter, "data");
ILibDuktape_CreateInstanceMethod(ctx, "send", ILibDuktape_ScriptContainer_Slave_SendToMaster, 1);
}

View File

@@ -1,11 +1,11 @@
/*
Copyright 2006 - 2017 Intel Corporation
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
@@ -144,9 +144,10 @@ void ILibDuktape_ScriptContainer_CheckEmbedded(char **argv, char **script, int *
void ILibDuktape_ScriptContainer_InitMaster(void *chain, char *exePath, ILibProcessPipe_Manager manager);
int ILibDuktape_ScriptContainer_StartSlave(void *chain, ILibProcessPipe_Manager manager);
duk_context *ILibDuktape_ScriptContainer_InitializeJavaScriptEngine_minimal();
duk_context *ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx3(duk_context *ctx, 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 *ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx2(SCRIPT_ENGINE_SETTINGS *settings);
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);
#define ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx(securityFlags, executionTimeout, chain, argList, db, exePath, pipeManager, exitHandler, exitUser) ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx3(ILibDuktape_ScriptContainer_InitializeJavaScriptEngine_minimal(), (securityFlags), (executionTimeout), (chain), (argList), (db), (exePath), (pipeManager), (exitHandler), (exitUser))
#define ILibDuktape_ScriptContainer_InitializeJavaScriptEngine(securityFlags, executionTimeout, chain, pp_argList, db, exitHandler, exitUser) ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx((securityFlags), (executionTimeout), (chain), (pp_argList), (db), NULL, NULL, (exitHandler), (exitUser))
SCRIPT_ENGINE_SETTINGS *ILibDuktape_ScriptContainer_GetSettings(duk_context *ctx);

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006 - 2017 Intel Corporation
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -179,6 +179,17 @@ duk_ret_t ILibDuktape_SimpleDataStore_Keys(duk_context *ctx)
ILibSimpleDataStore_EnumerateKeys(ds, ILibDuktape_SimpleDataStore_Keys_EnumerationSink, &enumerator);
return 1;
}
duk_ret_t ILibDuktape_SimpleDataStore_Delete(duk_context *ctx)
{
duk_push_this(ctx); // [DataStore]
duk_get_prop_string(ctx, -1, ILibDuktape_DataStore_PTR); // [DataStore][ptr]
ILibSimpleDataStore ds = (ILibSimpleDataStore)duk_get_pointer(ctx, -1);
duk_size_t keyLen;
char *key = (char*)duk_get_lstring(ctx, 0, &keyLen);
ILibSimpleDataStore_DeleteEx(ds, key, (int)keyLen);
return(0);
}
duk_ret_t ILibDuktape_SimpleDataStore_Create(duk_context *ctx)
{
ILibSimpleDataStore dataStore;
@@ -214,6 +225,7 @@ duk_ret_t ILibDuktape_SimpleDataStore_Create(duk_context *ctx)
duk_push_pointer(ctx, dataStore); // [DataStore][RetVal][ds]
duk_put_prop_string(ctx, -2, ILibDuktape_DataStore_PTR);// [DataStore][RetVal]
ILibDuktape_CreateInstanceMethod(ctx, "Delete", ILibDuktape_SimpleDataStore_Delete, 1);
ILibDuktape_CreateInstanceMethod(ctx, "Put", ILibDuktape_SimpleDataStore_Put, 2);
ILibDuktape_CreateInstanceMethod(ctx, "Get", ILibDuktape_SimpleDataStore_Get, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "Compact", ILibDuktape_SimpleDataStore_Compact, 0);

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006 - 2017 Intel Corporation
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006 - 2017 Intel Corporation
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -44,11 +44,7 @@ typedef struct ILibWebRTC_Duktape_Handlers
void *ConnectionObject;
ILibDuktape_EventEmitter *emitter;
void *OnConnect;
void *OnDataChannel;
void *OnConnectionSendOK;
void *OnCandidate;
void *OnDisconnect;
}ILibWebRTC_Duktape_Handlers;
typedef struct ILibDuktape_WebRTC_DataChannel
{
@@ -56,7 +52,6 @@ typedef struct ILibDuktape_WebRTC_DataChannel
duk_context *ctx;
ILibDuktape_EventEmitter *emitter;
ILibDuktape_DuplexStream *stream;
void *OnAck;
}ILibDuktape_WebRTC_DataChannel;
extern void* ILibWrapper_WebRTC_Connection_GetStunModule(ILibWrapper_WebRTC_Connection connection);
@@ -170,7 +165,8 @@ void ILibDuktape_WebRTC_DataChannel_OnClose(struct ILibWrapper_WebRTC_DataChanne
void ILibDuktape_WebRTC_DataChannel_OnData(struct ILibWrapper_WebRTC_DataChannel* dataChannel, char* data, int dataLen, int dataType)
{
ILibDuktape_WebRTC_DataChannel *ptrs = (ILibDuktape_WebRTC_DataChannel*)dataChannel->userData;
if (ptrs != NULL) { ILibDuktape_DuplexStream_WriteData(ptrs->stream, data, dataLen); }
if (ptrs != NULL) { ILibDuktape_DuplexStream_WriteDataEx(ptrs->stream, dataType == 51 ? 1 : 0, data, dataLen); }
}
duk_ret_t ILibDuktape_WebRTC_DataChannel_Finalizer(duk_context *ctx)
{
@@ -178,12 +174,14 @@ duk_ret_t ILibDuktape_WebRTC_DataChannel_Finalizer(duk_context *ctx)
ILibDuktape_WebRTC_DataChannel *ptrs = (ILibDuktape_WebRTC_DataChannel*)Duktape_GetBuffer(ctx, -1, NULL);
if (ptrs->dataChannel != NULL)
{
printf("WebRTC Data Channel Finalizer on Connection: %p\n", ptrs->dataChannel->parent);
ptrs->dataChannel->userData = NULL;
ILibWrapper_WebRTC_DataChannel_Close(ptrs->dataChannel);
}
return 0;
}
void ILibDuktape_WebRTC_DataChannel_PUSH(duk_context *ctx, ILibWrapper_WebRTC_DataChannel *dataChannel)
{
if (dataChannel == NULL) { duk_push_null(ctx); return; }
@@ -195,6 +193,7 @@ void ILibDuktape_WebRTC_DataChannel_PUSH(duk_context *ctx, ILibWrapper_WebRTC_Da
dataChannel->OnRawData = ILibDuktape_WebRTC_DataChannel_OnData;
duk_push_object(ctx); // [dataChannel]
ILibDuktape_WriteID(ctx, "webRTC.dataChannel");
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_WebRTC_DataChannel)); // [dataChannel][buffer]
ptrs = (ILibDuktape_WebRTC_DataChannel*)Duktape_GetBuffer(ctx, -1, NULL);
dataChannel->userData = ptrs;
@@ -209,7 +208,8 @@ void ILibDuktape_WebRTC_DataChannel_PUSH(duk_context *ctx, ILibWrapper_WebRTC_Da
duk_push_int(ctx, dataChannel->streamId);
duk_put_prop_string(ctx, -2, "id");
ILibDuktape_EventEmitter_CreateEvent(ptrs->emitter, "ack", &(ptrs->OnAck));
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "ack");
ptrs->stream = ILibDuktape_DuplexStream_Init(ctx, ILibDuktape_WebRTC_DataChannel_Stream_WriteSink, ILibDuktape_WebRTC_DataChannel_Stream_EndSink,
ILibDuktape_WebRTC_DataChannel_Stream_PauseSink, ILibDuktape_WebRTC_DataChannel_Stream_ResumeSink, ptrs);
}
@@ -221,6 +221,8 @@ duk_ret_t ILibDuktape_WebRTC_ConnectionFactory_Finalizer(duk_context *ctx)
duk_get_prop_string(ctx, 0, ILibDuktape_WebRTC_ConnectionFactoryPtr);
factory = (ILibWrapper_WebRTC_ConnectionFactory)duk_get_pointer(ctx, -1);
printf("WebRTC Factory Finalizer: %p\n", factory);
if (factory != NULL && ILibIsChainBeingDestroyed(chain) == 0)
{
ILibWrapper_WebRTC_ConnectionFactory_RemoveFromChain(factory);
@@ -228,48 +230,140 @@ duk_ret_t ILibDuktape_WebRTC_ConnectionFactory_Finalizer(duk_context *ctx)
return 0;
}
#ifdef _WEBRTCDEBUG
void ILibDuktape_WebRTC_Connection_Debug(void* dtlsSession, char* debugField, int data)
{
ILibHashtable *t = ILibChain_GetBaseHashtable(((ILibTransport*)dtlsSession)->ChainLink.ParentChain);
ILibWebRTC_Duktape_Handlers *ptrs = (ILibWebRTC_Duktape_Handlers*)ILibHashtable_Get(t, dtlsSession, NULL, 0);
if (ptrs != NULL)
{
if (strcmp(debugField, "OnHold") == 0)
{
ILibDuktape_EventEmitter_SetupEmit(ptrs->ctx, ptrs->ConnectionObject, "_hold"); // [emit][this][name]
}
else if (strcmp(debugField, "OnCongestionWindowSizeChanged") == 0)
{
ILibDuktape_EventEmitter_SetupEmit(ptrs->ctx, ptrs->ConnectionObject, "_congestionWindowSizeChange"); // [emit][this][name]
}
else if (strcmp(debugField, "OnRTTCalculated") == 0)
{
ILibDuktape_EventEmitter_SetupEmit(ptrs->ctx, ptrs->ConnectionObject, "_rttCalculated"); // [emit][this][name]
}
else if (strcmp(debugField, "OnFastRecovery") == 0)
{
ILibDuktape_EventEmitter_SetupEmit(ptrs->ctx, ptrs->ConnectionObject, "_fastRecovery"); // [emit][this][name]
}
else if (strcmp(debugField, "OnLastSackTime") == 0)
{
ILibDuktape_EventEmitter_SetupEmit(ptrs->ctx, ptrs->ConnectionObject, "_lastSackTime"); // [emit][this][name]
}
else if (strcmp(debugField, "OnLastSentTime") == 0)
{
ILibDuktape_EventEmitter_SetupEmit(ptrs->ctx, ptrs->ConnectionObject, "_lastSentTime"); // [emit][this][name]
}
else if (strcmp(debugField, "OnReceiverCredits") == 0)
{
ILibDuktape_EventEmitter_SetupEmit(ptrs->ctx, ptrs->ConnectionObject, "_receiverCredits"); // [emit][this][name]
}
else if (strcmp(debugField, "OnT3RTX") == 0)
{
ILibDuktape_EventEmitter_SetupEmit(ptrs->ctx, ptrs->ConnectionObject, "_t3tx"); // [emit][this][name]
}
else if (strcmp(debugField, "OnSendRetry") == 0)
{
ILibDuktape_EventEmitter_SetupEmit(ptrs->ctx, ptrs->ConnectionObject, "_retransmit"); // [emit][this][name]
}
else if (strcmp(debugField, "OnSACKReceived") == 0)
{
ILibDuktape_EventEmitter_SetupEmit(ptrs->ctx, ptrs->ConnectionObject, "_sackReceived"); // [emit][this][name]
}
else if (strcmp(debugField, "OnRetryPacket") == 0)
{
duk_push_external_buffer(ptrs->ctx); // [extBuffer]
ILibDuktape_EventEmitter_SetupEmit(ptrs->ctx, ptrs->ConnectionObject, "_retransmitPacket"); // [extBuffer][emit][this][name]
duk_config_buffer(ptrs->ctx, -4, debugField + 14, data);
duk_push_buffer_object(ptrs->ctx, -4, 0, data, DUK_BUFOBJ_NODEJS_BUFFER);
if (duk_pcall_method(ptrs->ctx, 2) != 0) { ILibDuktape_Process_UncaughtException(ptrs->ctx); }
duk_pop_2(ptrs->ctx); // ...
return;
}
else
{
return;
}
duk_push_int(ptrs->ctx, data); // [emit][this][name][val]
if (duk_pcall_method(ptrs->ctx, 2) != 0) { ILibDuktape_Process_UncaughtException(ptrs->ctx); }
duk_pop(ptrs->ctx); // ...
}
}
#endif
void ILibDuktape_WebRTC_OnConnection(ILibWrapper_WebRTC_Connection connection, int connected)
{
ILibWebRTC_Duktape_Handlers *ptrs = (ILibWebRTC_Duktape_Handlers*)ILibMemory_GetExtraMemory(connection, ILibMemory_WebRTC_Connection_CONTAINERSIZE);
if (ptrs->OnConnect != NULL && connected != 0)
if (connected == 0)
{
duk_push_heapptr(ptrs->ctx, ptrs->OnConnect); // [func]
duk_push_heapptr(ptrs->ctx, ptrs->ConnectionObject); // [func][this]
if (duk_pcall_method(ptrs->ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ptrs->ctx, "webrtc.connection.onConnect(): "); }
duk_pop(ptrs->ctx); // ...
ILibDuktape_EventEmitter_SetupEmit(ptrs->ctx, ptrs->ConnectionObject, "disconnected"); // [emit][this][disconnected]
duk_del_prop_string(ptrs->ctx, -2, ILibDuktape_WebRTC_ConnectionPtr);
}
else if (ptrs->OnDisconnect != NULL && connected == 0)
else
{
duk_push_heapptr(ptrs->ctx, ptrs->OnDisconnect); // [func]
duk_push_heapptr(ptrs->ctx, ptrs->ConnectionObject); // [func][this]
if (duk_pcall_method(ptrs->ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ptrs->ctx, "webrtc.connection.onConnect(): "); }
duk_pop(ptrs->ctx); // ...
ILibDuktape_EventEmitter_SetupEmit(ptrs->ctx, ptrs->ConnectionObject, "connected"); // [emit][this][connected]
}
if (duk_pcall_method(ptrs->ctx, 1) != 0) { ILibDuktape_Process_UncaughtException(ptrs->ctx); }
duk_pop(ptrs->ctx); // ...
#ifdef _WEBRTCDEBUG
ILibHashtable *t = ILibChain_GetBaseHashtable(Duktape_GetChain(ptrs->ctx));
if (connected != 0)
{
ILibSCTP_Debug_SetDebugCallback(ILibWrapper_WebRTC_Connection2DtlsSession(connection), "OnHold", ILibDuktape_WebRTC_Connection_Debug);
ILibSCTP_Debug_SetDebugCallback(ILibWrapper_WebRTC_Connection2DtlsSession(connection), "OnCongestionWindowSizeChanged", ILibDuktape_WebRTC_Connection_Debug);
ILibSCTP_Debug_SetDebugCallback(ILibWrapper_WebRTC_Connection2DtlsSession(connection), "OnRTTCalculated", ILibDuktape_WebRTC_Connection_Debug);
ILibSCTP_Debug_SetDebugCallback(ILibWrapper_WebRTC_Connection2DtlsSession(connection), "OnFastRecovery", ILibDuktape_WebRTC_Connection_Debug);
ILibSCTP_Debug_SetDebugCallback(ILibWrapper_WebRTC_Connection2DtlsSession(connection), "OnReceiverCredits", ILibDuktape_WebRTC_Connection_Debug);
ILibSCTP_Debug_SetDebugCallback(ILibWrapper_WebRTC_Connection2DtlsSession(connection), "OnT3RTX", ILibDuktape_WebRTC_Connection_Debug);
ILibSCTP_Debug_SetDebugCallback(ILibWrapper_WebRTC_Connection2DtlsSession(connection), "OnSendRetry", ILibDuktape_WebRTC_Connection_Debug);
ILibSCTP_Debug_SetDebugCallback(ILibWrapper_WebRTC_Connection2DtlsSession(connection), "OnSendFastRetry", ILibDuktape_WebRTC_Connection_Debug);
ILibSCTP_Debug_SetDebugCallback(ILibWrapper_WebRTC_Connection2DtlsSession(connection), "OnRetryPacket", ILibDuktape_WebRTC_Connection_Debug);
ILibSCTP_Debug_SetDebugCallback(ILibWrapper_WebRTC_Connection2DtlsSession(connection), "OnSACKReceived", ILibDuktape_WebRTC_Connection_Debug);
ILibHashtable_Put(t, ILibWrapper_WebRTC_Connection2DtlsSession(connection), NULL, 0, ptrs);
}
else
{
ILibSCTP_Debug_SetDebugCallback(ILibWrapper_WebRTC_Connection2DtlsSession(connection), "OnHold", NULL);
ILibSCTP_Debug_SetDebugCallback(ILibWrapper_WebRTC_Connection2DtlsSession(connection), "OnCongestionWindowSizeChanged", NULL);
ILibSCTP_Debug_SetDebugCallback(ILibWrapper_WebRTC_Connection2DtlsSession(connection), "OnRTTCalculated", NULL);
ILibSCTP_Debug_SetDebugCallback(ILibWrapper_WebRTC_Connection2DtlsSession(connection), "OnFastRecovery", NULL);
ILibSCTP_Debug_SetDebugCallback(ILibWrapper_WebRTC_Connection2DtlsSession(connection), "OnReceiverCredits", NULL);
ILibSCTP_Debug_SetDebugCallback(ILibWrapper_WebRTC_Connection2DtlsSession(connection), "OnT3RTX", NULL);
ILibSCTP_Debug_SetDebugCallback(ILibWrapper_WebRTC_Connection2DtlsSession(connection), "OnSendRetry", NULL);
ILibSCTP_Debug_SetDebugCallback(ILibWrapper_WebRTC_Connection2DtlsSession(connection), "OnSendFastRetry", NULL);
ILibSCTP_Debug_SetDebugCallback(ILibWrapper_WebRTC_Connection2DtlsSession(connection), "OnRetryPacket", NULL);
ILibSCTP_Debug_SetDebugCallback(ILibWrapper_WebRTC_Connection2DtlsSession(connection), "OnSACKReceived", NULL);
ILibHashtable_Remove(t, ILibWrapper_WebRTC_Connection2DtlsSession(connection), NULL, 0);
}
#endif
}
void ILibDuktape_WebRTC_OnDataChannel(ILibWrapper_WebRTC_Connection connection, ILibWrapper_WebRTC_DataChannel *dataChannel)
{
ILibWebRTC_Duktape_Handlers *ptrs = (ILibWebRTC_Duktape_Handlers*)ILibMemory_GetExtraMemory(connection, ILibMemory_WebRTC_Connection_CONTAINERSIZE);
if (ptrs->OnDataChannel != NULL)
{
duk_push_heapptr(ptrs->ctx, ptrs->OnDataChannel); // [func]
duk_push_heapptr(ptrs->ctx, ptrs->ConnectionObject); // [func][this]
ILibDuktape_WebRTC_DataChannel_PUSH(ptrs->ctx, dataChannel);// [func][this][dataChannel]
if (duk_pcall_method(ptrs->ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ptrs->ctx, "webrtc.connection.onDataChannel(): "); }
duk_pop(ptrs->ctx); // ...
}
ILibDuktape_EventEmitter_SetupEmit(ptrs->ctx, ptrs->ConnectionObject, "dataChannel"); // [emit][this][dataChannel]
ILibDuktape_WebRTC_DataChannel_PUSH(ptrs->ctx, dataChannel); // [emit][this][dataChannel][dc]
if (duk_pcall_method(ptrs->ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ptrs->ctx, "webrtc.connection.onDataChannel(): "); }
duk_pop(ptrs->ctx); // ...
}
void ILibDuktape_WebRTC_offer_onCandidate(ILibWrapper_WebRTC_Connection connection, struct sockaddr_in6* candidate)
{
ILibWebRTC_Duktape_Handlers *ptrs = (ILibWebRTC_Duktape_Handlers*)ILibMemory_GetExtraMemory(connection, ILibMemory_WebRTC_Connection_CONTAINERSIZE);
if (ptrs->OnCandidate != NULL)
if (candidate != NULL)
{
duk_push_heapptr(ptrs->ctx, ptrs->OnCandidate); // [func]
duk_push_heapptr(ptrs->ctx, ptrs->ConnectionObject); // [func][this]
ILibDuktape_SockAddrToOptions(ptrs->ctx, candidate); // [func][this][options]
if (duk_pcall_method(ptrs->ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ptrs->ctx, "webrtc.connection.onCandidate(): "); }
ILibWebRTC_Duktape_Handlers *ptrs = (ILibWebRTC_Duktape_Handlers*)ILibMemory_GetExtraMemory(connection, ILibMemory_WebRTC_Connection_CONTAINERSIZE);
ILibDuktape_EventEmitter_SetupEmit(ptrs->ctx, ptrs->ConnectionObject, "candidate"); // [emit][this][candidate]
ILibDuktape_SockAddrToOptions(ptrs->ctx, candidate); // [emit][this][candidate][options]
if (duk_pcall_method(ptrs->ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ptrs->ctx, "webrtc.connection.onCandidate(): "); }
duk_pop(ptrs->ctx); // ...
}
}
@@ -307,20 +401,16 @@ duk_ret_t ILibDuktape_WebRTC_setOffer(duk_context *ctx)
}
else
{
duk_push_null(ctx);
return(ILibDuktape_Error(ctx, "WebRTC: Error setting offer. Most likely too many outstanding offers"));
}
return 1;
}
void ILibDuktape_WebRTC_DataChannel_OnAck(struct ILibWrapper_WebRTC_DataChannel* dataChannel)
{
ILibDuktape_WebRTC_DataChannel *ptrs = (ILibDuktape_WebRTC_DataChannel*)dataChannel->userData;
if (ptrs->OnAck != NULL)
{
duk_push_heapptr(ptrs->ctx, ptrs->OnAck); // [func]
duk_push_heapptr(ptrs->ctx, ptrs->emitter->object); // [func][this]
if (duk_pcall_method(ptrs->ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ptrs->ctx, "webrtc.dataChannel.onAck(): "); };
duk_pop(ptrs->ctx); // ...
}
ILibDuktape_EventEmitter_SetupEmit(ptrs->ctx, ptrs->emitter->object, "ack"); // [emit][this][ack]
if (duk_pcall_method(ptrs->ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ptrs->ctx, "webrtc.dataChannel.onAck(): "); };
duk_pop(ptrs->ctx); // ...
}
duk_ret_t ILibDuktape_WebRTC_createDataChannel(duk_context *ctx)
{
@@ -378,8 +468,13 @@ duk_ret_t ILibDuktape_WebRTC_Connection_Finalizer(duk_context *ctx)
ILibWrapper_WebRTC_Connection connection;
duk_get_prop_string(ctx, 0, ILibDuktape_WebRTC_ConnectionPtr);
connection = (ILibWrapper_WebRTC_Connection)duk_get_pointer(ctx, -1);
printf("WebRTCConnection Finalizer on %p\n", (void*)connection);
if (connection == NULL) { return 0; }
#ifdef _WEBRTCDEBUG
ILibHashtable_Remove(ILibChain_GetBaseHashtable(Duktape_GetChain(ctx)), ILibWrapper_WebRTC_Connection2DtlsSession(connection), NULL, 0);
#endif
if (ILibWrapper_WebRTC_Connection_IsConnected(connection) != 0)
{
ILibWrapper_WebRTC_Connection_CloseAllDataChannels(connection);
@@ -398,17 +493,31 @@ duk_ret_t ILibDuktape_WebRTC_CreateConnection(duk_context *ctx)
factory = (ILibWrapper_WebRTC_ConnectionFactory)duk_get_pointer(ctx, -1);
duk_push_object(ctx); // [factory][connection]
ILibDuktape_WriteID(ctx, "webRTC.peerConnection");
connection = ILibWrapper_WebRTC_ConnectionFactory_CreateConnection2(factory, ILibDuktape_WebRTC_OnConnection, ILibDuktape_WebRTC_OnDataChannel, NULL, sizeof(ILibWebRTC_Duktape_Handlers));
ptrs = (ILibWebRTC_Duktape_Handlers*)ILibMemory_GetExtraMemory(connection, ILibMemory_WebRTC_Connection_CONTAINERSIZE);
ptrs->ctx = ctx;
ptrs->ConnectionObject = duk_get_heapptr(ctx, -1);
ptrs->emitter = ILibDuktape_EventEmitter_Create(ctx);
ILibDuktape_EventEmitter_CreateEvent(ptrs->emitter, "candidate", &(ptrs->OnCandidate));
ILibDuktape_EventEmitter_CreateEvent(ptrs->emitter, "dataChannel", &(ptrs->OnDataChannel));
ILibDuktape_EventEmitter_CreateEvent(ptrs->emitter, "connected", &(ptrs->OnConnect));
ILibDuktape_EventEmitter_CreateEvent(ptrs->emitter, "disconnected", &(ptrs->OnDisconnect));
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "candidate");
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "dataChannel");
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "connected");
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "disconnected");
#ifdef _WEBRTCDEBUG
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "_hold");
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "_lastSackTime");
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "_lastSentTime");
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "_congestionWindowSizeChange");
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "_fastRecovery");
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "_rttCalculated");
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "_receiverCredits");
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "_t3tx");
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "_retransmit");
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "_retransmitPacket");
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "_sackReceived");
#endif
duk_push_pointer(ctx, connection); // [factory][connection][ptr]
duk_put_prop_string(ctx, -2, ILibDuktape_WebRTC_ConnectionPtr); // [factory][connection]
@@ -429,6 +538,7 @@ void ILibDuktape_WebRTC_Push(duk_context *ctx, void *chain)
ILibWrapper_WebRTC_ConnectionFactory factory;
duk_push_object(ctx); // [factory]
ILibDuktape_WriteID(ctx, "webRTC");
factory = ILibWrapper_WebRTC_ConnectionFactory_CreateConnectionFactory(chain, 0);
duk_push_pointer(ctx, factory); // [factory][ptr]
duk_put_prop_string(ctx, -2, ILibDuktape_WebRTC_ConnectionFactoryPtr); // [factory]

View File

@@ -1,3 +1,19 @@
/*
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef ___ILibDuktape_WebRTC___
#define ___ILibDuktape_WebRTC___

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006 - 2017 Intel Corporation
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ limitations under the License.
#include "ILibDuktape_Helpers.h"
#include "ILibDuktape_WritableStream.h"
#include "ILibDuktape_EventEmitter.h"
#include "ILibDuktape_Polyfills.h"
#ifdef __DOXY__
/*!
@@ -118,11 +119,13 @@ void ILibDuktape_WritableStream_Ready(ILibDuktape_WritableStream *stream)
}
duk_pop(stream->ctx); // ...
}
else if (stream->OnDrain != NULL)
else
{
duk_push_heapptr(stream->ctx, stream->OnDrain); // [func]
duk_push_heapptr(stream->ctx, stream->obj); // [func][this]
if (duk_pcall_method(stream->ctx, 0) != 0) // [retVal]
duk_push_heapptr(stream->ctx, stream->obj); // [this]
duk_get_prop_string(stream->ctx, -1, "emit"); // [this][emit]
duk_swap_top(stream->ctx, -2); // [emit][this]
duk_push_string(stream->ctx, "drain"); // [emit][this][drain]
if (duk_pcall_method(stream->ctx, 1) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(stream->ctx);
}
@@ -132,20 +135,17 @@ void ILibDuktape_WritableStream_Ready(ILibDuktape_WritableStream *stream)
else
{
// End of Stream
if (stream->OnFinish != NULL)
{
duk_push_heapptr(stream->ctx, stream->OnFinish); // [func]
duk_push_heapptr(stream->ctx, stream->obj); // [func][this]
if (duk_pcall_method(stream->ctx, 0) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(stream->ctx);
}
duk_pop(stream->ctx); // ...
}
if (stream->EndSink != NULL)
{
stream->EndSink(stream, stream->WriteSink_User);
}
duk_push_heapptr(stream->ctx, stream->obj); // [stream]
duk_get_prop_string(stream->ctx, -1, "emit"); // [stream][emit]
duk_swap_top(stream->ctx, -2); // [emit][this]
duk_push_string(stream->ctx, "finish"); // [emit][this][finish]
if (duk_pcall_method(stream->ctx, 1) != 0) { ILibDuktape_Process_UncaughtException(stream->ctx); }
duk_pop(stream->ctx); // ...
}
}
@@ -167,6 +167,7 @@ duk_ret_t ILibDuktape_WritableStream_Write(duk_context *ctx)
if (stream->WriteSink != NULL)
{
stream->endBytes = -1;
switch (stream->WriteSink(stream, buffer, (int)bufferLen, stream->WriteSink_User))
{
case ILibTransport_DoneState_COMPLETE:
@@ -192,19 +193,18 @@ duk_ret_t ILibDuktape_WritableStream_Write(duk_context *ctx)
duk_push_false(ctx);
break;
default:
if (stream->OnError != NULL)
duk_push_heapptr(ctx, stream->obj); // [this]
duk_get_prop_string(ctx, -1, "emit"); // [this][emit]
duk_swap_top(ctx, -2); // [emit][this]
duk_push_string(ctx, "error"); // [emit][this][error]
duk_push_object(ctx); // [emit][this][error][errorObj]
duk_push_string(ctx, "ILibDuktape_WritableStream_Write");
duk_put_prop_string(ctx, -2, "stack");
duk_push_string(ctx, "ILibDuktape_WriteableStream_Write/Handler returned Error");
duk_put_prop_string(ctx, -2, "message");
if (duk_pcall_method(ctx, 2) != 0) // [retVal]
{
duk_push_heapptr(ctx, stream->OnError); // [func]
duk_push_heapptr(ctx, stream->obj); // [func][this]
duk_push_object(ctx); // [func][this][error]
duk_push_string(ctx, "ILibDuktape_WritableStream_Write");
duk_put_prop_string(ctx, -2, "stack");
duk_push_string(ctx, "ILibDuktape_WriteableStream_Write/Handler returned Error");
duk_put_prop_string(ctx, -2, "message");
if (duk_pcall_method(ctx, 1) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(ctx);
}
ILibDuktape_Process_UncaughtException(ctx);
}
duk_push_false(ctx);
break;
@@ -230,10 +230,7 @@ duk_ret_t ILibDuktape_WritableStream_End(duk_context *ctx)
{
if (nargs > 2 && !duk_is_null_or_undefined(ctx, 2))
{
stream->OnFinish = duk_require_heapptr(ctx, 2);
duk_push_this(ctx); // [stream]
duk_dup(ctx, 2); // [stream][flush]
duk_put_prop_string(ctx, -2, "_Finish"); // [stream]
ILibDuktape_EventEmitter_AddOnce(ILibDuktape_EventEmitter_GetEmitter_fromThis(ctx), "finish", duk_require_heapptr(ctx, 2));
}
stream->endBytes = (int)bufferLen;
if (stream->WriteSink(stream, buffer, (int)bufferLen, stream->WriteSink_User) == ILibTransport_DoneState_INCOMPLETE)
@@ -247,16 +244,14 @@ duk_ret_t ILibDuktape_WritableStream_End(duk_context *ctx)
if (stream->WaitForEnd == 0)
{
// Continue with closing stream
if (stream->OnFinish != NULL)
{
duk_push_heapptr(ctx, stream->OnFinish); // [func]
duk_push_heapptr(ctx, stream->obj); // [func][this]
if (duk_pcall_method(ctx, 0) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(ctx);
}
}
if (stream->EndSink != NULL) { stream->EndSink(stream, stream->WriteSink_User); }
duk_push_heapptr(stream->ctx, stream->obj); // [stream]
duk_get_prop_string(stream->ctx, -1, "emit"); // [stream][emit]
duk_swap_top(stream->ctx, -2); // [emit][this]
duk_push_string(stream->ctx, "finish"); // [emit][this][finish]
if (duk_pcall_method(stream->ctx, 1) != 0) { ILibDuktape_Process_UncaughtException(stream->ctx); }
duk_pop(stream->ctx); // ...
}
return 0;
@@ -268,9 +263,20 @@ duk_ret_t ILibDuktape_WritableStream_End_Getter(duk_context *ctx)
}
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"));
ILibDuktape_WritableStream *ws;
duk_dup(ctx, 0); // [readable]
duk_push_this(ctx); // [readable][writable]
if (duk_has_prop_string(ctx, -1, ILibDuktape_WritableStream_WSPTRS))
{
duk_get_prop_string(ctx, -1, ILibDuktape_WritableStream_WSPTRS); // [readable][writable][ptr]
ws = (ILibDuktape_WritableStream*)Duktape_GetBuffer(ctx, -1, NULL);
ws->pipedReadable = NULL;
ws->pipedReadable_native = NULL;
duk_pop(ctx); // [readable][writable]
if (g_displayStreamPipeMessages) { printf("UNPIPE: [%s] => X => [%s:%d]\n", Duktape_GetStringPropertyValue(ctx, -2, ILibDuktape_OBJID, "unknown"), Duktape_GetStringPropertyValue(ctx, -1, ILibDuktape_OBJID, "unknown"), ILibDuktape_GetReferenceCount(ctx, -1) - 1); if (g_displayFinalizerMessages) { duk_eval_string(ctx, "_debugGC();"); duk_pop(ctx); } }
}
duk_pop_2(ctx);
return(0);
}
duk_ret_t ILibDuktape_WritableStream_PipeSink(duk_context *ctx)
@@ -289,8 +295,7 @@ duk_ret_t ILibDuktape_WritableStream_PipeSink(duk_context *ctx)
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"));
if (g_displayStreamPipeMessages) { printf("PIPE: [%s] => [%s:%d]\n", Duktape_GetStringPropertyValue(ctx, -2, ILibDuktape_OBJID, "unknown"), Duktape_GetStringPropertyValue(ctx, -1, ILibDuktape_OBJID, "unknown"), ILibDuktape_GetReferenceCount(ctx, -1)); }
return(0);
}
@@ -315,11 +320,11 @@ ILibDuktape_WritableStream* ILibDuktape_WritableStream_Init(duk_context *ctx, IL
emitter = ILibDuktape_EventEmitter_Create(ctx);
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));
ILibDuktape_EventEmitter_CreateEventEx(emitter, "drain");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "finish");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "error");
ILibDuktape_CreateInstanceMethod(ctx, "write", ILibDuktape_WritableStream_Write, DUK_VARARGS);
ILibDuktape_CreateProperty_InstanceMethod(ctx, "write", ILibDuktape_WritableStream_Write, DUK_VARARGS);
ILibDuktape_CreateEventWithGetter(ctx, "end", ILibDuktape_WritableStream_End_Getter);
ILibDuktape_EventEmitter_AddOnEx(ctx, -1, "pipe", ILibDuktape_WritableStream_PipeSink);

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006 - 2017 Intel Corporation
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -33,14 +33,10 @@ typedef struct ILibDuktape_WritableStream
int JSCreated;
duk_context *ctx;
void *obj;
void *OnDrain;
void *OnWriteFlush;
ILibDuktape_WriteableStream_WriteFlushNative OnWriteFlushEx;
void *OnWriteFlushEx_User;
void *OnError;
void *OnFinish;
char WaitForEnd;
ILibDuktape_WritableStream_WriteHandler WriteSink;

View File

@@ -1,11 +1,11 @@
/*
Copyright 2006 - 2017 Intel Corporation
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
@@ -69,7 +69,6 @@ typedef struct ILibDuktape_fs_writeStreamData
ILibDuktape_EventEmitter *emitter;
void *fsObject;
void *WriteStreamObject;
void *onClose;
FILE *fPtr;
int fd;
int autoClose;
@@ -82,7 +81,6 @@ typedef struct ILibDuktape_fs_readStreamData
void *ReadStreamObject;
void *fsObject;
ILibDuktape_EventEmitter *emitter;
void *onClose;
FILE *fPtr;
int fd;
int autoClose;
@@ -99,7 +97,6 @@ typedef struct ILibDuktape_fs_watcherData
duk_context *ctx;
void *object;
void *parent;
void *OnChange;
ILibDuktape_EventEmitter *emitter;
#if defined(WIN32)
int recursive;
@@ -240,9 +237,7 @@ duk_ret_t ILibDuktape_fs_openSync(duk_context *ctx)
}
else
{
duk_push_string(ctx, "fs.openSync ERROR");
duk_throw(ctx);
return(DUK_RET_ERROR);
return(ILibDuktape_Error(ctx, "fs.openSync(): Error opening '%s'", path));
}
}
duk_ret_t ILibDuktape_fs_readSync(duk_context *ctx)
@@ -260,7 +255,7 @@ duk_ret_t ILibDuktape_fs_readSync(duk_context *ctx)
{
if (duk_is_number(ctx, 4))
{
fseek(f, duk_require_int(ctx, 4), SEEK_CUR);
fseek(f, duk_require_int(ctx, 4), SEEK_SET);
}
bytesRead = (int)fread(buffer + offset, 1, length, f);
duk_push_int(ctx, bytesRead);
@@ -285,7 +280,7 @@ duk_ret_t ILibDuktape_fs_writeSync(duk_context *ctx)
f = ILibDuktape_fs_getFilePtr(ctx, duk_require_int(ctx, 0));
if (f != NULL)
{
if (nargs > 4) { fseek(f, duk_require_int(ctx, 4), SEEK_CUR); }
if (nargs > 4) { fseek(f, duk_require_int(ctx, 4), SEEK_SET); printf("Write: Seeking to %d\n", duk_require_int(ctx, 4)); }
bytesWritten = (int)fwrite(buffer, 1, length, f);
duk_push_int(ctx, bytesWritten);
return 1;
@@ -339,17 +334,14 @@ void ILibDuktape_fs_writeStream_endHandler(struct ILibDuktape_WritableStream *st
data->fPtr = NULL;
}
if (data->ctx != NULL && data->onClose != NULL)
{
// Call the 'close' event on the WriteStream
duk_push_heapptr(data->ctx, data->onClose); // [func]
duk_push_heapptr(data->ctx, data->WriteStreamObject); // [func][this]
if (duk_pcall_method(data->ctx, 0) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(data->ctx);
}
duk_pop(data->ctx);
}
// Call the 'close' event on the WriteStream
duk_push_heapptr(data->ctx, data->WriteStreamObject); // [this]
duk_get_prop_string(data->ctx, -1, "emit"); // [this][emit]
duk_swap_top(data->ctx, -2); // [emit][this]
duk_push_string(data->ctx, "close"); // [emit][this][close]
if (duk_pcall_method(data->ctx, 1) != 0) { ILibDuktape_Process_UncaughtException(data->ctx); }
duk_pop(data->ctx); // ...
}
duk_ret_t ILibDuktape_fs_writeStream_finalizer(duk_context *ctx)
{
@@ -413,6 +405,7 @@ duk_ret_t ILibDuktape_fs_createWriteStream(duk_context *ctx)
if (f != NULL)
{
duk_push_object(ctx); // [writeStream]
ILibDuktape_WriteID(ctx, "fs.writeStream");
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_fs_writeStreamData)); // [writeStream][buffer]
data = (ILibDuktape_fs_writeStreamData*)Duktape_GetBuffer(ctx, -1, NULL);
memset(data, 0, sizeof(ILibDuktape_fs_writeStreamData));
@@ -428,7 +421,7 @@ duk_ret_t ILibDuktape_fs_createWriteStream(duk_context *ctx)
data->emitter = ILibDuktape_EventEmitter_Create(ctx);
data->stream = ILibDuktape_WritableStream_Init(ctx, ILibDuktape_fs_writeStream_writeHandler, ILibDuktape_fs_writeStream_endHandler, data);
ILibDuktape_EventEmitter_CreateEvent(data->emitter, "close", &(data->onClose));
ILibDuktape_EventEmitter_CreateEventEx(data->emitter, "close");
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_fs_writeStream_finalizer);
return 1;
}
@@ -454,14 +447,15 @@ void ILibDuktape_fs_readStream_Resume(struct ILibDuktape_readableStream *sender,
sender->paused = 0;
if (data->bytesRead == -1) { data->bytesRead = 1; }
while (sender->paused == 0 && data->bytesRead > 0 && data->bytesLeft < 0)
while (sender->paused == 0 && data->bytesRead > 0 && (data->bytesLeft < 0 || data->bytesLeft > 0))
{
bytesToRead = data->bytesLeft < 0 ? sizeof(data->buffer) : data->bytesLeft;
bytesToRead = data->bytesLeft < 0 ? sizeof(data->buffer) : (data->bytesLeft > sizeof(data->buffer) ? sizeof(data->buffer) : data->bytesLeft);
data->bytesRead = (int)fread(data->buffer, 1, bytesToRead, data->fPtr);
if (data->bytesRead > 0)
{
if (data->bytesLeft > 0) { data->bytesLeft -= data->bytesRead; }
ILibDuktape_readableStream_WriteData(sender, data->buffer, data->bytesRead);
if (data->bytesLeft == 0) { data->bytesRead = 0; }
}
}
if (sender->paused == 0 && data->bytesRead == 0)
@@ -477,14 +471,13 @@ void ILibDuktape_fs_readStream_Resume(struct ILibDuktape_readableStream *sender,
data->fd = 0;
data->fPtr = NULL;
if (data->onClose != NULL && data->ctx != NULL)
if (data->ctx != NULL && data->ReadStreamObject != NULL)
{
duk_push_heapptr(data->ctx, data->onClose); // [func]
duk_push_heapptr(data->ctx, data->ReadStreamObject); // [func][this]
if (duk_pcall_method(data->ctx, 0) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(data->ctx);
}
duk_push_heapptr(data->ctx, data->ReadStreamObject); // [this]
duk_get_prop_string(data->ctx, -1, "emit"); // [this][emit]
duk_swap_top(data->ctx, -2); // [emit][this]
duk_push_string(data->ctx, "close"); // [emit][this][close]
if (duk_pcall_method(data->ctx, 1) != 0) { ILibDuktape_Process_UncaughtException(data->ctx); }
duk_pop(data->ctx); // ...
}
}
@@ -551,6 +544,7 @@ duk_ret_t ILibDuktape_fs_createReadStream(duk_context *ctx)
}
duk_push_object(ctx); // [readStream]
ILibDuktape_WriteID(ctx, "fs.readStream");
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_fs_readStreamData)); // [readStream][buffer]
data = (ILibDuktape_fs_readStreamData*)Duktape_GetBuffer(ctx, -1, NULL);
memset(data, 0, sizeof(ILibDuktape_fs_readStreamData));
@@ -564,17 +558,19 @@ duk_ret_t ILibDuktape_fs_createReadStream(duk_context *ctx)
data->fPtr = f;
data->autoClose = autoClose;
data->ReadStreamObject = duk_get_heapptr(ctx, -1);
data->bytesLeft = end;
data->bytesLeft = end < 0 ? end : (end - start + 1);
data->bytesRead = -1;
data->stream = ILibDuktape_ReadableStream_Init(ctx, ILibDuktape_fs_readStream_Pause, ILibDuktape_fs_readStream_Resume, data);
data->stream->paused = 1;
ILibDuktape_EventEmitter_CreateEvent(data->emitter, "close", &(data->onClose));
//printf("readStream [start: %d, end: %d\n", start, end);
ILibDuktape_EventEmitter_CreateEventEx(data->emitter, "close");
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_fs_readStream_finalizer);
if (start != 0)
{
fseek(f, start, SEEK_CUR);
fseek(f, start, SEEK_SET);
}
return 1;
@@ -904,24 +900,23 @@ void ILibDuktape_fs_watch_iocompletionEx(void *chain, void *user)
n = (n->NextEntryOffset != 0) ? ((FILE_NOTIFY_INFORMATION*)((char*)n + n->NextEntryOffset)) : NULL;
}
if (data->OnChange != NULL)
duk_push_heapptr(data->ctx, data->object); // [detail][fsWatcher]
duk_get_prop_string(data->ctx, -1, "emit"); // [detail][fsWatcher][emit]
duk_swap_top(data->ctx, -2); // [detail][emit][this]
duk_push_string(data->ctx, "change"); // [detail][emit][this][change]
duk_push_string(data->ctx, changed == 0 ? "rename" : "change"); // [detail][emit][this][change][type]
if (changed == 0)
{
duk_push_heapptr(data->ctx, data->OnChange); // [detail][change]
duk_push_heapptr(data->ctx, data->object); // [detail][change][fsWatcher]
duk_push_string(data->ctx, changed == 0 ? "rename" : "change"); // [detail][change][fsWatcher][type]
if (changed == 0)
{
duk_get_prop_string(data->ctx, -4, "oldname"); // [detail][listener][fsWatcher][type][fileName]
}
else
{
duk_get_prop_string(data->ctx, -4, "\xFF_FileName"); // [detail][listener][fsWatcher][type][fileName]
}
duk_dup(data->ctx, -5); // [detail][change][fsWatcher][type][fileName][detail]
if (duk_pcall_method(data->ctx, 3) != 0) { ILibDuktape_Process_UncaughtException(data->ctx); }
duk_pop(data->ctx); // [detail]
duk_get_prop_string(data->ctx, -4, "oldname"); // [detail][emit][this][change][type][fileName]
}
duk_pop(data->ctx); // ...
else
{
duk_get_prop_string(data->ctx, -4, "\xFF_FileName"); // [detail][emit][this][change][type][fileName]
}
duk_dup(data->ctx, -5); // [detail][emit][this][change][type][fileName][detail]
if (duk_pcall_method(data->ctx, 4) != 0) { ILibDuktape_Process_UncaughtException(data->ctx); }
duk_pop_2(data->ctx); // ...
memset(data->results, 0, sizeof(data->results));
if (data->h != NULL)
@@ -1001,7 +996,7 @@ void ILibDuktape_fs_notifyDispatcher_PostSelect(void* object, int slct, fd_set *
wd.p = NULL;
wd.i = evt->wd;
watcher = (ILibDuktape_fs_watcherData*)ILibHashtable_Get(data->watchTable, wd.p, NULL, 0);
if (watcher == NULL || watcher->OnChange == NULL) { continue; }
if (watcher == NULL || ILibDuktape_EventEmitter_HasListeners(watcher->emitter, "change") == 0) { continue; }
duk_push_object(watcher->ctx); // [detail]
@@ -1021,21 +1016,19 @@ void ILibDuktape_fs_notifyDispatcher_PostSelect(void* object, int slct, fd_set *
duk_push_string(watcher->ctx, evt->name);
duk_put_prop_string(watcher->ctx, -2, "\xFF_FileName");
}
duk_push_heapptr(watcher->ctx, watcher->OnChange); // [detail][change]
duk_push_heapptr(watcher->ctx, watcher->object); // [detail][change][fsWatcher]
duk_push_string(watcher->ctx, changed == 0 ? "rename" : "change"); // [detail][change][fsWatcher][type]
ILibDuktape_EventEmitter_SetupEmit(watcher->ctx, watcher->object, "change");// [detail][emit][this][change]
duk_push_string(watcher->ctx, changed == 0 ? "rename" : "change"); // [detail][emit][this][change][type]
if (changed == 0)
{
duk_get_prop_string(watcher->ctx, -4, "oldname"); // [detail][listener][fsWatcher][type][fileName]
duk_get_prop_string(watcher->ctx, -5, "oldname"); // [detail][emit][this][change][type][fileName]
}
else
{
duk_get_prop_string(watcher->ctx, -4, "\xFF_FileName"); // [detail][listener][fsWatcher][type][fileName]
duk_get_prop_string(watcher->ctx, -5, "\xFF_FileName"); // [detail][emit][this][change][type][fileName]
}
duk_dup(watcher->ctx, -5); // [detail][change][fsWatcher][type][fileName][detail]
if (duk_pcall_method(watcher->ctx, 3) != 0) { ILibDuktape_Process_UncaughtException(watcher->ctx); }
duk_pop_2(watcher->ctx); // ...
duk_dup(watcher->ctx, -6); // [detail][emit][this][change][type][fileName][detail]
if (duk_pcall_method(watcher->ctx, 4) != 0) { ILibDuktape_Process_UncaughtException(watcher->ctx); }
duk_pop_2(watcher->ctx); // ...
}
}
}
@@ -1099,6 +1092,7 @@ duk_ret_t ILibDuktape_fs_watch(duk_context *ctx)
#endif
duk_push_object(ctx); // [FSWatcher]
ILibDuktape_WriteID(ctx, "fs.fsWatcher");
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_fs_watcherData)); // [FSWatcher][data]
data = (ILibDuktape_fs_watcherData*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, FS_WATCHER_DATA_PTR); // [FSWatcher]
@@ -1117,7 +1111,7 @@ duk_ret_t ILibDuktape_fs_watch(duk_context *ctx)
ILibDuktape_CreateInstanceMethod(ctx, "close", ILibDuktape_fs_watcher_close, 0);
ILibDuktape_EventEmitter_CreateEvent(data->emitter, "change", &(data->OnChange));
ILibDuktape_EventEmitter_CreateEventEx(data->emitter, "change");
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_fs_watcher_finalizer);
for (i = 1; i < nargs; ++i)
@@ -1233,10 +1227,26 @@ duk_ret_t ILibDuktape_fs_readFileSync(duk_context *ctx)
return(1);
}
duk_ret_t ILibDuktape_fs_existsSync(duk_context *ctx)
{
duk_push_this(ctx); // [fs]
duk_get_prop_string(ctx, -1, "statSync"); // [fs][statSync]
duk_swap_top(ctx, -2); // [statSync][this]
duk_dup(ctx, 0); // [statSync][this][path]
if (duk_pcall_method(ctx, 1) != 0)
{
duk_push_false(ctx);
}
else
{
duk_push_true(ctx);
}
return(1);
}
void ILibDuktape_fs_PUSH(duk_context *ctx, void *chain)
{
duk_push_object(ctx); // [fs]
ILibDuktape_WriteID(ctx, "fs");
duk_push_pointer(ctx, chain); // [fs][chain]
duk_put_prop_string(ctx, -2, FS_CHAIN_PTR); // [fs]
@@ -1256,6 +1266,7 @@ void ILibDuktape_fs_PUSH(duk_context *ctx, void *chain)
ILibDuktape_CreateInstanceMethod(ctx, "statSync", ILibDuktape_fs_statSync, 1);
ILibDuktape_CreateInstanceMethod(ctx, "readDrivesSync", ILibDuktape_fs_readDrivesSync, 0);
ILibDuktape_CreateInstanceMethod(ctx, "readFileSync", ILibDuktape_fs_readFileSync, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "existsSync", ILibDuktape_fs_existsSync, 1);
#ifndef _NOFSWATCHER
ILibDuktape_CreateInstanceMethod(ctx, "watch", ILibDuktape_fs_watch, DUK_VARARGS);
#endif

View File

@@ -1,3 +1,19 @@
/*
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef ___DUKTAPE_FS___
#define ___DUKTAPE_FS___

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006 - 2017 Intel Corporation
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -41,14 +41,12 @@ limitations under the License.
duk_ret_t ILibDuktape_httpDigest_clientRequest_response2(duk_context *ctx)
{
ILibHTTPPacket *packet;
duk_get_prop_string(ctx, 0, "PacketPtr");
packet = (ILibHTTPPacket*)duk_get_pointer(ctx, -1);
duk_push_current_function(ctx);
duk_get_prop_string(ctx, -1, "digestClientRequest");// [digestClientRequest]
if (packet->StatusCode == 200)
int statusCode = Duktape_GetIntPropertyValue(ctx, 0, "statusCode", 0);
if (statusCode == 200)
{
duk_get_prop_string(ctx, -1, "emit"); // [digestClientRequest][emit]
duk_swap_top(ctx, -2); // [emit][this]
@@ -60,8 +58,8 @@ duk_ret_t ILibDuktape_httpDigest_clientRequest_response2(duk_context *ctx)
{
duk_get_prop_string(ctx, -1, "emit"); // [digestClientRequest][emit]
duk_swap_top(ctx, -2); // [emit][this]
duk_push_string(ctx, "error"); // [emit][this][response]
duk_dup(ctx, 0); // [emit][this][response][imsg]
duk_push_string(ctx, "error"); // [emit][this][error]
duk_dup(ctx, 0); // [emit][this][error][imsg]
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "http-digest: Error dispatching response event"); }
}
@@ -143,8 +141,8 @@ extern void ILibWebServer_Digest_ParseAuthenticationHeader(void* table, char* va
char *ILibDuktape_httpDigest_generateAuthenticationHeader(duk_context *ctx, void *digestObj, void *optionsObj)
{
int top = duk_get_top(ctx);
int NC;
char *CNONCE;
int NC = 0;
char *CNONCE = NULL;
char *wwwauth, *username, *password;
char *method, *path;
@@ -188,7 +186,9 @@ char *ILibDuktape_httpDigest_generateAuthenticationHeader(duk_context *ctx, void
}
else
{
duk_get_prop_string(ctx, -1, DIGEST2CNONCE); // [digest][buffer]
CNONCE = (char*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop(ctx); // [digest]
NC = Duktape_GetIntPropertyValue(ctx, -1, DIGEST2NC, 0) + 1;
duk_push_int(ctx, NC); // [digest][NC]
duk_put_prop_string(ctx, -2, DIGEST2NC); // [digest]
@@ -198,14 +198,10 @@ char *ILibDuktape_httpDigest_generateAuthenticationHeader(duk_context *ctx, void
util_md5hex(ILibScratchPad2, tmpLen, result3);
duk_pop(ctx); // ...
tmpLen = sprintf_s(ILibScratchPad2, sizeof(ILibScratchPad2), "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\"", username, realm, nonce, path);
if (opaque != NULL) { tmpLen += sprintf_s(ILibScratchPad2 + tmpLen, sizeof(ILibScratchPad2) - tmpLen, ", opaque=\"%s\"", opaque); }
if (qop != NULL)
{
tmpLen += sprintf_s(ILibScratchPad2 + tmpLen, sizeof(ILibScratchPad2) - tmpLen, ", qop=\"%s\", nc=%08x, cnonce=\"%s\"", qop, NC, CNONCE);
}
tmpLen += sprintf_s(ILibScratchPad2 + tmpLen, sizeof(ILibScratchPad2) - tmpLen, ", response=\"%s\"", result3);
tmpLen = sprintf_s(ILibScratchPad2, sizeof(ILibScratchPad2), "Digest username=\"%s\",realm=\"%s\",nonce=\"%s\",uri=\"%s\"", username, realm, nonce, path);
if (opaque != NULL) { tmpLen += sprintf_s(ILibScratchPad2 + tmpLen, sizeof(ILibScratchPad2) - tmpLen, ",opaque=\"%s\"", opaque); }
tmpLen += sprintf_s(ILibScratchPad2 + tmpLen, sizeof(ILibScratchPad2) - tmpLen, ",response=\"%s\"", result3);
if (qop != NULL) { tmpLen += sprintf_s(ILibScratchPad2 + tmpLen, sizeof(ILibScratchPad2) - tmpLen, ",qop=\"%s\",nc=\"%08x\",cnonce=\"%s\"", qop, NC, CNONCE); }
if (realmLen > 0) { realm[realmLen] = '"'; }
if (nonceLen > 0) { nonce[nonceLen] = '"'; }
@@ -305,8 +301,8 @@ duk_ret_t ILibDuktape_httpDigest_clientRequest_response(duk_context *ctx)
duk_dup(ctx, -2); // [clientRequest][buffer][clientRequest]
duk_get_prop_string(ctx, -1, "write"); // [clientRequest][buffer][clientRequest][write]
duk_swap_top(ctx, -2); // [clientRequest][buffer][write][this]
duk_swap(ctx, -3, -2); // [clientRequest][write][buffer][this]
duk_swap_top(ctx, -2); // [clientReqeust][write][this][buffer]
duk_dup(ctx, -3); // [clientRequest][buffer][write][this][buffer]
duk_remove(ctx, -4); // [clientRequest][write][this][buffer]
if (duk_pcall_method(ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "httpDigest.clientRequest.onResponse(): Error calling clientRequest.write(): "); }
duk_pop(ctx); // [clientRequest]
}
@@ -410,6 +406,12 @@ ILibTransport_DoneState ILibDuktape_httpDigest_http_request_WriteHandler(struct
duk_put_prop_string(ctx, -2, DIGESTCLIENTREQUEST_TmpBuffer); // [digestClientRequest]
memcpy_s(tmpBuffer, bufLen, buffer, (size_t)bufferLen);
}
if (stream->endBytes > 0)
{
duk_push_true(ctx);
duk_put_prop_string(ctx, -2, DIGESTCLIENTREQUEST_END_CALLED);
}
}
if (duk_has_prop_string(ctx, -1, DIGEST_CLIENT_REQUEST))
@@ -477,6 +479,7 @@ duk_ret_t ILibDuktape_httpDigest_http_request(duk_context *ctx)
void *clientRequest = NULL;
ILibDuktape_EventEmitter *emitter;
char *auth = NULL;
int needCallEnd = 0;
duk_push_this(ctx); // [digest]
duk_get_prop_string(ctx, -1, HTTP_DIGEST); // [digest][http]
@@ -489,6 +492,7 @@ duk_ret_t ILibDuktape_httpDigest_http_request(duk_context *ctx)
duk_dup(ctx, -2); // [digest][request][this][parseUri][this]
duk_dup(ctx, 0); // [digest][request][this][parseUri][this][uri]
duk_call_method(ctx, 1); // [digest][request][this][options]
needCallEnd = 1;
}
else
{
@@ -522,6 +526,13 @@ duk_ret_t ILibDuktape_httpDigest_http_request(duk_context *ctx)
duk_push_c_function(ctx, ILibDuktape_httpDigest_clientRequest_response, DUK_VARARGS); // [once][this][response][method]
duk_push_object(ctx); // [once][this][response][method][digest-clientRequest]
ILibDuktape_WriteID(ctx, "httpDigest.clientRequest");
if (needCallEnd)
{
duk_push_true(ctx);
duk_put_prop_string(ctx, -2, DIGESTCLIENTREQUEST_END_CALLED);
}
duk_push_this(ctx); // [once][this][response][method][digest-clientRequest][digest]
duk_put_prop_string(ctx, -2, DIGESTCLIENTREQUEST_DIGEST); // [once][this][response][method][digest-clientRequest]
duk_push_heapptr(ctx, clientRequest); // [once][this][response][method][digest-clientRequest][clientRequest]
@@ -557,6 +568,13 @@ duk_ret_t ILibDuktape_httpDigest_http_request(duk_context *ctx)
ILibDuktape_EventEmitter_ForwardEvent(ctx, -2, "timeout", -1, "timeout");
ILibDuktape_EventEmitter_ForwardEvent(ctx, -2, "drain", -1, "drain");
if (needCallEnd)
{
duk_get_prop_string(ctx, -2, "end"); // [clientRequest][digestClientRequest][end]
duk_dup(ctx, -3); // [clientRequest][digestClientRequest][end][this]
duk_call_method(ctx, 0); duk_pop(ctx); // [clientRequest][digestClientRequest]
}
return(1);
}
duk_ret_t ILibduktape_httpDigest_create(duk_context *ctx)
@@ -566,6 +584,7 @@ duk_ret_t ILibduktape_httpDigest_create(duk_context *ctx)
ILibDuktape_EventEmitter *emitter;
duk_push_object(ctx); // [obj]
ILibDuktape_WriteID(ctx, "httpDigest");
ILibDuktape_CreateEventWithSetterEx(ctx, "clientRequest", ILibDuktape_httpDigest_clientRequest_setter);
ILibDuktape_CreateEventWithSetterEx(ctx, "http", ILibDuktape_httpDigest_http_setter);
emitter = ILibDuktape_EventEmitter_Create(ctx);
@@ -580,6 +599,7 @@ duk_ret_t ILibduktape_httpDigest_create(duk_context *ctx)
duk_put_prop_string(ctx, -2, DIGEST_PASSWORD);
duk_push_fixed_buffer(ctx, 16);
util_randomtext(16, (char*)Duktape_GetBuffer(ctx, -1, NULL));
((char*)Duktape_GetBuffer(ctx, -1, NULL))[15] = 0;
duk_put_prop_string(ctx, -2, DIGEST2CNONCE);
duk_push_int(ctx, 0);
duk_put_prop_string(ctx, -2, DIGEST2NC);

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006 - 2017 Intel Corporation
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006 - 2017 Intel Corporation
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -34,10 +34,6 @@ typedef struct ILibDuktape_net_socket
void *net;
void *duplexStream;
void *chain;
void *OnConnect;
void *OnClose;
void *OnError;
void *OnTimeout;
void *OnSetTimeout;
int unshiftBytes;
ILibDuktape_EventEmitter *emitter;
@@ -53,9 +49,7 @@ typedef struct ILibDuktape_net_server
void *self;
ILibAsyncServerSocket_ServerModule server;
ILibDuktape_EventEmitter *emitter;
void *OnClose;
void *OnListening;
void *OnError;
int isTLS;
}ILibDuktape_net_server;
typedef struct ILibDuktape_net_server_session
{
@@ -66,8 +60,6 @@ typedef struct ILibDuktape_net_server_session
ILibDuktape_DuplexStream *stream;
int unshiftBytes;
void *OnTimeout;
}ILibDuktape_net_server_session;
int ILibDuktape_TLS_ctx2socket = -1;
@@ -83,6 +75,7 @@ int ILibDuktape_TLS_ctx2server = -1;
#define ILibDuktape_SERVER2ContextTable "\xFF_Server2ContextTable"
#define ILibDuktape_SERVER2OPTIONS "\xFF_ServerToOptions"
#define ILibDuktape_SERVER2LISTENOPTIONS "\xFF_ServerToListenOptions"
#define ILibDuktape_TLSSocket2SecureContext "\xFF_TLSSocket2SecureContext"
extern void ILibAsyncServerSocket_RemoveFromChain(ILibAsyncServerSocket_ServerModule serverModule);
@@ -143,28 +136,34 @@ void ILibDuktape_net_socket_OnConnect(ILibAsyncSocket_SocketModule socketModule,
return;
}
#endif
if (ptrs->OnConnect != NULL)
{
duk_push_heapptr(ptrs->ctx, ptrs->OnConnect); // [func]
duk_push_heapptr(ptrs->ctx, ptrs->object); // [func][this]
if (duk_pcall_method(ptrs->ctx, 0) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(ptrs->ctx);
}
duk_pop(ptrs->ctx); // ...
}
duk_push_heapptr(ptrs->ctx, ptrs->object); // [this]
duk_get_prop_string(ptrs->ctx, -1, "emit"); // [this][emit]
duk_swap_top(ptrs->ctx, -2); // [emit][this]
duk_push_string(ptrs->ctx, "connect"); // [emit][this][connect]
if (duk_pcall_method(ptrs->ctx, 1) != 0) { ILibDuktape_Process_UncaughtException(ptrs->ctx); }
duk_pop(ptrs->ctx); // ...
}
else if(ptrs->OnError != NULL)
else
{
duk_push_heapptr(ptrs->ctx, ptrs->OnError); // [func]
ILibDuktape_net_socket_PUSH(ptrs->ctx, socketModule); // [func][this]
duk_push_object(ptrs->ctx); // [func][this][error]
duk_push_string(ptrs->ctx, "Connection Failed"); // [func][this][error][msg]
duk_put_prop_string(ptrs->ctx, -2, "message"); // [func][this][error]
if (duk_pcall_method(ptrs->ctx, 1) != 0) // [retVal]
duk_push_heapptr(ptrs->ctx, ptrs->object); // [this]
duk_get_prop_string(ptrs->ctx, -1, "emit"); // [this][emit]
duk_swap_top(ptrs->ctx, -2); // [emit][this]
duk_push_string(ptrs->ctx, "error"); // [emit][this][error]
duk_push_object(ptrs->ctx); // [emit][this][error][errorObj]
#ifndef MICROSTACK_NOTLS
if (ptrs->ssl != NULL && ILibAsyncSocket_TLS_WasHandshakeError(socketModule))
{
ILibDuktape_Process_UncaughtException(ptrs->ctx);
duk_push_string(ptrs->ctx, "TLS Handshake Error"); // [emit][this][error][errorObj][msg]
}
else
{
duk_push_string(ptrs->ctx, "Connection Failed"); // [emit][this][error][errorObj][msg]
}
#else
duk_push_string(ptrs->ctx, "Connection Failed"); // [emit][this][error][errorObj][msg]
#endif
duk_put_prop_string(ptrs->ctx, -2, "message"); // [emit][this][error][errorObj]
if (duk_pcall_method(ptrs->ctx, 2) != 0) { ILibDuktape_Process_UncaughtException(ptrs->ctx); }
duk_pop(ptrs->ctx); // ...
}
}
@@ -338,13 +337,13 @@ duk_ret_t ILibDuktape_net_socket_address(duk_context *ctx)
void ILibDuktape_net_socket_timeoutSink(ILibAsyncSocket_SocketModule socketModule, void *user)
{
ILibDuktape_net_socket *ptrs = (ILibDuktape_net_socket*)((ILibChain_Link*)socketModule)->ExtraMemoryPtr;
if (ptrs->OnTimeout != NULL)
{
duk_push_heapptr(ptrs->ctx, ptrs->OnTimeout); // [func]
duk_push_heapptr(ptrs->ctx, ptrs->object); // [func][this]
if (duk_pcall_method(ptrs->ctx, 0) != 0) { ILibDuktape_Process_UncaughtException(ptrs->ctx); }
duk_pop(ptrs->ctx); // ...
}
duk_push_heapptr(ptrs->ctx, ptrs->object); // [this]
duk_get_prop_string(ptrs->ctx, -1, "emit"); // [this][emit]
duk_swap_top(ptrs->ctx, -2); // [emit][this]
duk_push_string(ptrs->ctx, "timeout"); // [emit][this][timeout]
if (duk_pcall_method(ptrs->ctx, 1) != 0) { ILibDuktape_Process_UncaughtException(ptrs->ctx); }
duk_pop(ptrs->ctx); // ...
}
duk_ret_t ILibDuktape_net_socket_setTimeout(duk_context *ctx)
{
@@ -378,9 +377,6 @@ duk_ret_t ILibDuktape_net_socket_finalizer(duk_context *ctx)
if (ptrs->socketModule != NULL)
{
if (ILibAsyncSocket_IsConnected(ptrs->socketModule) != 0) { ILibAsyncSocket_Disconnect(ptrs->socketModule); }
#ifndef MICROSTACK_NOTLS
if (ptrs->ssl_ctx != NULL) { SSL_CTX_free(ptrs->ssl_ctx); ptrs->ssl_ctx = NULL; }
#endif
ILibChain_SafeRemove(chain, ptrs->socketModule);
}
@@ -423,10 +419,10 @@ void ILibDuktape_net_socket_PUSH(duk_context *ctx, ILibAsyncSocket_SocketModule
ptrs->emitter = ILibDuktape_EventEmitter_Create(ctx);
ptrs->duplexStream = ILibDuktape_DuplexStream_InitEx(ctx, ILibDuktape_net_socket_WriteHandler, ILibDuktape_net_socket_EndHandler, ILibDuktape_net_socket_PauseHandler, ILibDuktape_net_socket_ResumeHandler, ILibDuktape_net_socket_unshift, ptrs);
ILibDuktape_EventEmitter_CreateEvent(ptrs->emitter, "close", &(ptrs->OnClose));
ILibDuktape_EventEmitter_CreateEvent(ptrs->emitter, "connect", &(ptrs->OnConnect));
ILibDuktape_EventEmitter_CreateEvent(ptrs->emitter, "error", &(ptrs->OnError));
ILibDuktape_EventEmitter_CreateEvent(ptrs->emitter, "timeout", &(ptrs->OnTimeout));
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "close");
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "connect");
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "error");
ILibDuktape_EventEmitter_CreateEventEx(ptrs->emitter, "timeout");
ILibDuktape_CreateProperty_InstanceMethod(ctx, "connect", ILibDuktape_net_socket_connect, DUK_VARARGS);
@@ -576,7 +572,7 @@ void ILibDuktape_net_server_OnConnect(ILibAsyncServerSocket_ServerModule AsyncSe
session->emitter = ILibDuktape_EventEmitter_Create(ptr->ctx);
ILibDuktape_EventEmitter_CreateEvent(session->emitter, "timeout", &(session->OnTimeout));
ILibDuktape_EventEmitter_CreateEventEx(session->emitter, "timeout");
session->stream = ILibDuktape_DuplexStream_InitEx(ptr->ctx, ILibDuktape_net_server_WriteSink, ILibDuktape_net_server_EndSink,
ILibDuktape_net_server_PauseSink, ILibDuktape_net_server_ResumeSink, ILibDuktape_net_server_unshiftSink, session);
@@ -587,7 +583,7 @@ void ILibDuktape_net_server_OnConnect(ILibAsyncServerSocket_ServerModule AsyncSe
void ILibDuktape_net_server_OnDisconnect(ILibAsyncServerSocket_ServerModule AsyncServerSocketModule, ILibAsyncServerSocket_ConnectionToken ConnectionToken, void *user)
{
ILibDuktape_net_server_session *session = (ILibDuktape_net_server_session*)user;
ILibDuktape_DuplexStream_WriteEnd(session->stream);
ILibDuktape_DuplexStream_Closed(session->stream);
}
void ILibDuktape_net_server_OnReceive(ILibAsyncServerSocket_ServerModule AsyncServerSocketModule, ILibAsyncServerSocket_ConnectionToken ConnectionToken, char* buffer, int *p_beginPointer, int endPointer, ILibAsyncServerSocket_OnInterrupt *OnInterrupt, void **user, int *PAUSE)
{
@@ -689,34 +685,37 @@ duk_ret_t ILibDuktape_net_server_listen(duk_context *ctx)
ILibAsyncServerSocket_SetTag(server->server, server);
#ifndef MICROSTACK_NOTLS
{
duk_push_this(ctx); // [server]
if (duk_has_prop_string(ctx, -1, "addContext"))
if (server->isTLS)
{
duk_get_prop_string(ctx, -1, "addContext"); // [server][addContext]
duk_swap_top(ctx, -2); // [addContext][this]
duk_push_string(ctx, "*"); // [addContext][this][*]
duk_eval_string(ctx, "require('tls');"); // [addContext][this][*][tls]
duk_get_prop_string(ctx, -1, "createSecureContext"); // [addContext][this][*][tls][createSecureContext]
duk_swap_top(ctx, -2); // [addContext][this][*][createSecureContext][this]
duk_get_prop_string(ctx, -4, ILibDuktape_SERVER2OPTIONS); // [addContext][this][*][createSecureContext][this][options]
duk_call_method(ctx, 1); // [addContext][this][*][secureContext]
duk_call_method(ctx, 2); duk_pop(ctx); // ...
}
else
{
duk_pop(ctx); // ...
duk_push_this(ctx); // [server]
if (duk_has_prop_string(ctx, -1, "addContext"))
{
duk_get_prop_string(ctx, -1, "addContext"); // [server][addContext]
duk_swap_top(ctx, -2); // [addContext][this]
duk_push_string(ctx, "*"); // [addContext][this][*]
duk_eval_string(ctx, "require('tls');"); // [addContext][this][*][tls]
duk_get_prop_string(ctx, -1, "createSecureContext"); // [addContext][this][*][tls][createSecureContext]
duk_swap_top(ctx, -2); // [addContext][this][*][createSecureContext][this]
duk_get_prop_string(ctx, -4, ILibDuktape_SERVER2OPTIONS); // [addContext][this][*][createSecureContext][this][options]
duk_call_method(ctx, 1); // [addContext][this][*][secureContext]
duk_call_method(ctx, 2); duk_pop(ctx); // ...
}
else
{
duk_pop(ctx); // ...
}
}
}
#endif
if (server->OnListening != NULL)
{
duk_push_heapptr(server->ctx, server->OnListening); // [func]
duk_push_heapptr(server->ctx, server->self); // [func][this]
if (duk_pcall_method(server->ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(server->ctx, "net.server.listen(): Error "); }
duk_pop(server->ctx); // ...
}
duk_push_heapptr(server->ctx, server->self); // [this]
duk_get_prop_string(server->ctx, -1, "emit"); // [this][emit]
duk_swap_top(server->ctx, -2); // [emit][this]
duk_push_string(server->ctx, "listening"); // [emit][this][listenting]
if (duk_pcall_method(server->ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(server->ctx, "net.server.listen(): Error "); }
duk_pop(server->ctx); // ...
#ifndef WIN32
ignore_result(backlog);
#endif
@@ -783,11 +782,12 @@ duk_ret_t ILibDuktape_net_createServer(duk_context *ctx)
server = (ILibDuktape_net_server*)Duktape_GetBuffer(ctx, -1, NULL);
memset(server, 0, sizeof(ILibDuktape_net_server));
duk_put_prop_string(ctx, -2, ILibDuktape_net_Server_buffer); // [server]
server->isTLS = isTLS;
server->self = duk_get_heapptr(ctx, -1);
server->ctx = ctx;
server->emitter = ILibDuktape_EventEmitter_Create(ctx);
ILibDuktape_EventEmitter_CreateEvent(server->emitter, "close", &(server->OnClose));
ILibDuktape_EventEmitter_CreateEventEx(server->emitter, "close");
ILibDuktape_EventEmitter_CreateEventEx(server->emitter, "connection");
#ifndef MICROSTACK_NOTLS
if (isTLS)
@@ -799,8 +799,8 @@ duk_ret_t ILibDuktape_net_createServer(duk_context *ctx)
if (ILibDuktape_TLS_ctx2server < 0) { ILibDuktape_TLS_ctx2server = SSL_get_ex_new_index(0, "ILibDuktape_TLS_Server index", NULL, NULL, NULL); }
}
#endif
ILibDuktape_EventEmitter_CreateEvent(server->emitter, "error", &(server->OnError));
ILibDuktape_EventEmitter_CreateEvent(server->emitter, "listening", &(server->OnListening));
ILibDuktape_EventEmitter_CreateEventEx(server->emitter, "error");
ILibDuktape_EventEmitter_CreateEventEx(server->emitter, "listening");
ILibDuktape_CreateInstanceMethod(ctx, "listen", ILibDuktape_net_server_listen, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "address", ILibDuktape_net_server_address, 0);
@@ -816,6 +816,13 @@ duk_ret_t ILibDuktape_net_createServer(duk_context *ctx)
if (duk_is_object(ctx, i))
{
// Options
if (isTLS && !duk_has_prop_string(ctx, i, "secureProtocol"))
{
duk_dup(ctx, i); // [options]
duk_push_string(ctx, "SSLv23_server_method"); // [options][secureProtocol]
duk_put_prop_string(ctx, -2, "secureProtocol"); // [options]
duk_pop(ctx); // ...
}
}
}
@@ -974,7 +981,7 @@ int ILibDuktape_TLS_verify(int preverify_ok, X509_STORE_CTX *storectx)
if (Duktape_GetBooleanProperty(data->ctx, -1, "rejectUnauthorized", 1)) { duk_pop_2(data->ctx); return(preverify_ok); }
void *OnVerify = Duktape_GetHeapptrProperty(data->ctx, -1, "checkServerIdentity");
if (OnVerify == NULL) { return(1); }
if (OnVerify == NULL) { duk_pop_2(data->ctx); return(1); }
duk_push_heapptr(data->ctx, OnVerify); // [func]
duk_push_heapptr(data->ctx, data->object); // [func][this]
@@ -1141,10 +1148,6 @@ duk_ret_t ILibDuktape_TLS_connect(duk_context *ctx)
ILibAsyncSocket_SocketModule module = ILibCreateAsyncSocketModuleWithMemory(Duktape_GetChain(ctx), 4096, ILibDuktape_net_socket_OnData, ILibDuktape_net_socket_OnConnect, ILibDuktape_net_socket_OnDisconnect, ILibDuktape_net_socket_OnSendOK, sizeof(ILibDuktape_net_socket));
ILibDuktape_net_socket *data = (ILibDuktape_net_socket*)((ILibChain_Link*)module)->ExtraMemoryPtr;
data->ssl_ctx = SSL_CTX_new(SSLv23_client_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);
SSL_CTX_set_verify(data->ssl_ctx, SSL_VERIFY_PEER, ILibDuktape_TLS_verify); /* Ask for authentication */
if (ILibDuktape_TLS_ctx2socket < 0)
{
ILibDuktape_TLS_ctx2socket = SSL_get_ex_new_index(0, "ILibDuktape_TLS index", NULL, NULL, NULL);
@@ -1152,6 +1155,28 @@ duk_ret_t ILibDuktape_TLS_connect(duk_context *ctx)
ILibDuktape_net_socket_PUSH(ctx, module); // [socket]
ILibDuktape_WriteID(ctx, "tls.socket");
duk_dup(ctx, 0); // [socket][options]
if (duk_has_prop_string(ctx, -1, "secureContext"))
{
duk_get_prop_string(ctx, -1, "secureContext"); // [socket][options][secureContext]
}
else
{
duk_push_this(ctx); // [socket][options][tls]
duk_get_prop_string(ctx, -1, "createSecureContext"); // [socket][options][tls][createSecureContext]
duk_swap_top(ctx, -2); // [socket][options][createSecureContext][this]
duk_dup(ctx, -3); // [socket][options][createSecureContext][this][options]
duk_call_method(ctx, 1); // [socket][options][secureContext]
}
if ((data->ssl_ctx = (SSL_CTX*)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_SecureContext2SSLCTXPTR)) == NULL)
{
return(ILibDuktape_Error(ctx, "Invalid SecureContext Object"));
}
SSL_CTX_set_verify(data->ssl_ctx, SSL_VERIFY_PEER, ILibDuktape_TLS_verify); /* Ask for authentication */
duk_remove(ctx, -2); // [socket][secureContext]
duk_put_prop_string(ctx, -2, ILibDuktape_TLSSocket2SecureContext);
duk_dup(ctx, 0); // [socket][options]
duk_put_prop_string(ctx, -2, ILibDuktape_SOCKET2OPTIONS); // [socket]
ILibDuktape_EventEmitter_CreateEventEx(data->emitter, "secureConnect");
@@ -1197,6 +1222,7 @@ duk_ret_t ILibDuktape_TLS_connect(duk_context *ctx)
SSL_set_ex_data(data->ssl, ILibDuktape_TLS_ctx2socket, data);
SSL_set_tlsext_host_name(data->ssl, host);
}
return(1);
}
duk_ret_t ILibDuktape_TLS_secureContext_Finalizer(duk_context *ctx)
@@ -1211,6 +1237,7 @@ duk_ret_t ILibDuktape_TLS_secureContext_Finalizer(duk_context *ctx)
duk_ret_t ILibDuktape_TLS_createSecureContext(duk_context *ctx)
{
duk_push_object(ctx); // [secureContext]
ILibDuktape_WriteID(ctx, "tls.secureContext");
duk_push_fixed_buffer(ctx, sizeof(struct util_cert)); // [secureContext][cert]
struct util_cert *cert = (struct util_cert*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, ILibDuktape_SecureContext2CertBuffer); // [secureContext]
@@ -1218,14 +1245,69 @@ duk_ret_t ILibDuktape_TLS_createSecureContext(duk_context *ctx)
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_TLS_secureContext_Finalizer);
duk_size_t secureProtocolLen;
char *secureProtocol = (char*)Duktape_GetStringPropertyValueEx(ctx, 0, "secureProtocol", "SSLv23_server_method", &secureProtocolLen);
char *secureProtocol = (char*)Duktape_GetStringPropertyValueEx(ctx, 0, "secureProtocol", "SSLv23_method", &secureProtocolLen);
SSL_CTX *ssl_ctx = NULL;
if (secureProtocolLen == 20 && strncmp(secureProtocol, "SSLv23_server_method", 20) == 0)
if (secureProtocolLen == 13 && strncmp(secureProtocol, "SSLv23_method", 13) == 0)
{
ssl_ctx = SSL_CTX_new(SSLv23_server_method());
ssl_ctx = SSL_CTX_new(TLS_method());
SSL_CTX_set_options(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);
}
else if (secureProtocolLen == 20 && strncmp(secureProtocol, "SSLv23_client_method", 20) == 0)
{
ssl_ctx = SSL_CTX_new(TLS_method());
SSL_CTX_set_options(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);
}
else if (secureProtocolLen == 20 && strncmp(secureProtocol, "SSLv23_server_method", 20) == 0)
{
ssl_ctx = SSL_CTX_new(TLS_method());
SSL_CTX_set_options(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);
}
else if (secureProtocolLen == 12 && strncmp(secureProtocol, "TLSv1_method", 12) == 0)
{
ssl_ctx = SSL_CTX_new(TLS_method());
SSL_CTX_set_options(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_1 | SSL_OP_NO_TLSv1_2);
}
else if (secureProtocolLen == 19 && strncmp(secureProtocol, "TLSv1_client_method", 19) == 0)
{
ssl_ctx = SSL_CTX_new(TLS_method());
SSL_CTX_set_options(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_1 | SSL_OP_NO_TLSv1_2);
}
else if (secureProtocolLen == 19 && strncmp(secureProtocol, "TLSv1_server_method", 19) == 0)
{
ssl_ctx = SSL_CTX_new(TLS_method());
SSL_CTX_set_options(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_1 | SSL_OP_NO_TLSv1_2);
}
else if (secureProtocolLen == 14 && strncmp(secureProtocol, "TLSv1_1_method", 14) == 0)
{
ssl_ctx = SSL_CTX_new(TLS_method());
SSL_CTX_set_options(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 | SSL_OP_NO_TLSv1_2);
}
else if (secureProtocolLen == 21 && strncmp(secureProtocol, "TLSv1_1_client_method", 21) == 0)
{
ssl_ctx = SSL_CTX_new(TLS_method());
SSL_CTX_set_options(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 | SSL_OP_NO_TLSv1_2);
}
else if (secureProtocolLen == 21 && strncmp(secureProtocol, "TLSv1_1_server_method", 21) == 0)
{
ssl_ctx = SSL_CTX_new(TLS_method());
SSL_CTX_set_options(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 | SSL_OP_NO_TLSv1_2);
}
else if (secureProtocolLen == 14 && strncmp(secureProtocol, "TLSv1_2_method", 14) == 0)
{
ssl_ctx = SSL_CTX_new(TLS_method());
SSL_CTX_set_options(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 | SSL_OP_NO_TLSv1_1);
}
else if (secureProtocolLen == 21 && strncmp(secureProtocol, "TLSv1_2_client_method", 21) == 0)
{
ssl_ctx = SSL_CTX_new(TLS_method());
SSL_CTX_set_options(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 | SSL_OP_NO_TLSv1_1);
}
else if (secureProtocolLen == 21 && strncmp(secureProtocol, "TLSv1_2_server_method", 21) == 0)
{
ssl_ctx = SSL_CTX_new(TLS_method());
SSL_CTX_set_options(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 | SSL_OP_NO_TLSv1_1);
}
else if (secureProtocolLen == 11 && strncmp(secureProtocol, "DTLS_method", 11) == 0)
{
ssl_ctx = SSL_CTX_new(DTLS_method());
@@ -1266,11 +1348,31 @@ duk_ret_t ILibDuktape_TLS_generateCertificate(duk_context *ctx)
duk_push_fixed_buffer(ctx, len);
memcpy_s((void*)Duktape_GetBuffer(ctx, -1, NULL), len, data, len);
duk_push_buffer_object(ctx, -1, 0, len, DUK_BUFOBJ_NODEJS_BUFFER);
ILibDuktape_WriteID(ctx, "tls.pfxCertificate");
util_free(data);
util_freecert(&cert);
return 1;
}
duk_ret_t ILibDuktape_TLS_loadpkcs7b(duk_context *ctx)
{
duk_size_t len;
char *buffer = (char*)Duktape_GetBuffer(ctx, 0, &len);
int val = util_from_pkcs7b_string(buffer, (int)len, NULL, 0);
char *out;
if (val > 0)
{
duk_push_fixed_buffer(ctx, val);
out = Duktape_GetBuffer(ctx, -1, NULL);
duk_push_buffer_object(ctx, -1, 0, val, DUK_BUFOBJ_NODEJS_BUFFER);
util_from_pkcs7b_string(buffer, (int)len, out, val);
return(1);
}
else
{
return(ILibDuktape_Error(ctx, "Error reading pkcs7b data"));
}
}
void ILibDuktape_tls_PUSH(duk_context *ctx, void *chain)
{
duk_push_object(ctx); // [TLS]
@@ -1278,6 +1380,7 @@ void ILibDuktape_tls_PUSH(duk_context *ctx, void *chain)
ILibDuktape_CreateInstanceMethod(ctx, "connect", ILibDuktape_TLS_connect, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "createSecureContext", ILibDuktape_TLS_createSecureContext, 1);
ILibDuktape_CreateInstanceMethod(ctx, "generateCertificate", ILibDuktape_TLS_generateCertificate, 1);
ILibDuktape_CreateInstanceMethod(ctx, "loadpkcs7b", ILibDuktape_TLS_loadpkcs7b, 1);
}
#endif

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006 - 2017 Intel Corporation
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -1,3 +1,19 @@
/*
Copyright 2006 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(_MINCORE)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
@@ -7,6 +23,7 @@
#include "ILibDuktape_EventEmitter.h"
#include "ILibDuktapeModSearch.h"
#include "ILibDuktape_Helpers.h"
#include "ILibDuktape_Polyfills.h"
#define ILibDuktape_EventEmitter_MaxEventNameLen 255
#define ILibDuktape_EventEmitter_Data "\xFF_EventEmitter_Data"
@@ -127,39 +144,19 @@ void ILibDuktape_EventEmitter_FinalizerEx(ILibHashtable sender, void *Key1, char
duk_pop_2(data->ctx); // ...
}
}
duk_ret_t ILibDuktape_EventEmitter_Finalizer(duk_context *ctx)
int ILibDuktape_EventEmitter_HasListeners(ILibDuktape_EventEmitter *emitter, char *eventName)
{
ILibDuktape_EventEmitter *data;
duk_get_prop_string(ctx, 0, ILibDuktape_EventEmitter_Data);
data = (ILibDuktape_EventEmitter*)Duktape_GetBuffer(ctx, -1, NULL);
// Check to see if this is the process object going away
if (ILibDuktape_GetProcessObject(ctx) == data->object)
int retVal = 0;
if (emitter->eventTable != NULL)
{
// We need to dispatch the 'exit' event
int exitCode = 0;
duk_push_heapptr(data->ctx, data->object); // [process]
if (duk_has_prop_string(data->ctx, -1, "\xFF_ExitCode"))
ILibLinkedList eventList = ILibHashtable_Get(emitter->eventTable, NULL, eventName, (int)strnlen_s(eventName, 255));
if (eventList != NULL)
{
duk_get_prop_string(data->ctx, -1, "\xFF_ExitCode"); // [process][exitCode]
exitCode = duk_get_int(data->ctx, -1);
duk_pop(data->ctx); // [process]
retVal = ILibLinkedList_GetCount(eventList);
}
duk_get_prop_string(data->ctx, -1, "emit"); // [process][emit]
duk_swap_top(data->ctx, -2); // [emit][this]
duk_push_string(data->ctx, "exit"); // [emit][this][eventName/exit]
duk_push_int(data->ctx, exitCode); // [emit][this][eventName/exit][exitCode]
duk_pcall_method(data->ctx, 2);
duk_pop(data->ctx);
}
// We need to clear the Native Dispatcher, while destroying the Hashtable
ILibHashtable_DestroyEx(data->eventTable, ILibDuktape_EventEmitter_FinalizerEx, data);
memset(data, 0, sizeof(ILibDuktape_EventEmitter));
return 0;
return(retVal);
}
duk_ret_t ILibDuktape_EventEmitter_emit(duk_context *ctx)
{
@@ -170,25 +167,24 @@ duk_ret_t ILibDuktape_EventEmitter_emit(duk_context *ctx)
void *self;
int nargs = duk_get_top(ctx);
ILibDuktape_EventEmitter *data;
void *node, *nextNode, *func, *dispatcher;
int i, j, count;
void **hptr;
void *node, *nextNode, *func;
int i, j;
void **emitList;
char *objid;
duk_push_this(ctx);
duk_push_this(ctx); // [this]
objid = Duktape_GetStringPropertyValue(ctx, -1, ILibDuktape_OBJID, "unknown");
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_TempObject); // [this][tmp]
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_Data); // [this][tmp][data]
data = (ILibDuktape_EventEmitter*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop_2(ctx); // [this]
self = duk_get_heapptr(ctx, -1);
duk_pop(ctx); // ...
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); }
dispatcher = ILibHashtable_Get(data->eventTable, ILibDuktape_EventEmitter_SetterFunc, name, (int)nameLen);
if (dispatcher == NULL) { return ILibDuktape_Error(ctx, "EventEmitter.emit(): Internal Error with event '%s'", name); }
if (eventList == NULL) { return ILibDuktape_Error(ctx, "EventEmitter.emit(): Event '%s' not found on object '%s'", name, objid); }
// Copy the list, so we can enumerate with local memory, so the list can be manipulated while we are dispatching
#ifdef WIN32
@@ -213,22 +209,6 @@ duk_ret_t ILibDuktape_EventEmitter_emit(duk_context *ctx)
}
emitList[i] = NULL;
// If no more listeners, we can set the hptr to NULL
if (ILibLinkedList_GetCount(eventList) == 0)
{
duk_push_heapptr(ctx, dispatcher); // [dispatcher]
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_HPTR_LIST); // [dispatcher][hptrList]
count = (int)duk_get_length(ctx, -1);
for (i = 0; i < count; ++i)
{
duk_get_prop_index(ctx, -1, i); // [dispatcher][hptrList][hptr]
hptr = (void**)duk_get_pointer(ctx, -1);
*hptr = NULL;
duk_pop(ctx); // [dispatcher][hptrList]
}
duk_pop_2(ctx); // ...
}
// Now that we have all the housekeeping stuff out of the way, we can actually dispatch our events
i = 0;
while ((func = emitList[i++]) != NULL)
@@ -241,13 +221,27 @@ duk_ret_t ILibDuktape_EventEmitter_emit(duk_context *ctx)
}
if (duk_pcall_method(ctx, nargs - 1) != 0)
{
return(ILibDuktape_Error(ctx, "EventEmitter.emit(): Event dispatch for '%s' threw an exception: %s", name, duk_safe_to_string(ctx, -1)));
return(ILibDuktape_Error(ctx, "EventEmitter.emit(): Event dispatch for '%s' on '%s' threw an exception: %s", name, objid, duk_safe_to_string(ctx, -1)));
}
duk_pop(ctx); // ...
}
duk_push_boolean(ctx, i > 1 ? 1 : 0);
return(1);
}
int ILibDuktape_EventEmitter_PrependOnce(duk_context *ctx, duk_idx_t i, char *eventName, duk_c_function func)
{
int retVal = 1;
duk_dup(ctx, i); // [this]
duk_get_prop_string(ctx, -1, "prependOnceListener"); // [this][prependOnce]
duk_swap_top(ctx, -2); // [prependOnce][this]
duk_push_string(ctx, eventName); // [prependOnce][this][eventName]
duk_push_c_function(ctx, func, DUK_VARARGS); // [prependOnce][this][eventName][func]
if (duk_pcall_method(ctx, 2) != 0) { retVal = 0; }
duk_pop(ctx); // ...
return(retVal);
}
int ILibDuktape_EventEmitter_AddOnce(ILibDuktape_EventEmitter *emitter, char *eventName, void *heapptr)
{
int retVal = 1;
@@ -315,8 +309,9 @@ duk_ret_t ILibDuktape_EventEmitter_on(duk_context *ctx)
void *callback = duk_require_heapptr(ctx, 1);
ILibDuktape_EventEmitter *data;
int once;
void *eventList, *node, *dispatcher, **hptr;
int i, count, prepend;
void *eventList, *node;
int prepend;
ILibDuktape_EventEmitter_HookHandler hookHandler = NULL;
duk_push_current_function(ctx);
once = Duktape_GetIntPropertyValue(ctx, -1, "once", 0);
@@ -333,8 +328,7 @@ duk_ret_t ILibDuktape_EventEmitter_on(duk_context *ctx)
{
return(ILibDuktape_Error(ctx, "EventEmitter.on(): Event '%s' not found", propName));
}
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)); }
hookHandler = ILibHashtable_Get(data->eventTable, ILibDuktape_EventEmitter_Hook, propName, (int)propNameLen);
node = prepend ? ILibLinkedList_AddHead(eventList, callback) : ILibLinkedList_AddTail(eventList, callback);
((int*)ILibLinkedList_GetExtendedMemory(node))[0] = once;
@@ -344,17 +338,7 @@ duk_ret_t ILibDuktape_EventEmitter_on(duk_context *ctx)
duk_push_heapptr(ctx, callback);
duk_put_prop_string(ctx, -2, Duktape_GetStashKey(callback)); // Save the callback to the tmp object, so it won't get GC'ed
duk_push_heapptr(ctx, dispatcher); // [dispatcher]
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_HPTR_LIST); // [dispatcher][hptrList]
count = (int)duk_get_length(ctx, -1);
for (i = 0; i < count; ++i)
{
duk_get_prop_index(ctx, -1, i); // [dispatcher][hptrList][hptr]
hptr = (void**)duk_get_pointer(ctx, -1);
*hptr = dispatcher;
duk_pop(ctx); // [dispatcher][hptrList]
}
if (hookHandler != NULL) { hookHandler(data, propName, callback); }
return 0;
}
ILibDuktape_EventEmitter* ILibDuktape_EventEmitter_GetEmitter_fromThis(duk_context *ctx)
@@ -406,36 +390,69 @@ duk_ret_t ILibDuktape_EventEmitter_removeAllListeners(duk_context *ctx)
duk_size_t eventNameLen;
char *eventName = Duktape_GetBuffer(ctx, 0, &eventNameLen);
ILibDuktape_EventEmitter *emitter = ILibDuktape_EventEmitter_GetEmitter_fromThis(ctx);
void *eventList, *dispatcher;
int count, i;
void **hptr;
void *eventList;
if (emitter != NULL)
{
eventList = ILibHashtable_Get(emitter->eventTable, NULL, eventName, (int)eventNameLen);
if (eventList == NULL) { return(ILibDuktape_Error(ctx, "EventEmitter.removeAllListeners(): Event '%s' not found", eventName)); }
dispatcher = ILibHashtable_Get(emitter->eventTable, ILibDuktape_EventEmitter_SetterFunc, eventName, (int)eventNameLen);
if (dispatcher == NULL) { return(ILibDuktape_Error(ctx, "EventEmitter.removeAllListeners(): Internal error with Event '%s'", eventName)); }
// NULL was passed, we'll need to clear all listeners.
// Start by setting the Native Dispatcher to NULL, so it appears there are no subscribers
duk_push_heapptr(ctx, dispatcher); // [dispatcher]
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_HPTR_LIST); // [dispatcher][hptrList]
count = (int)duk_get_length(ctx, -1);
for (i = 0; i < count; ++i)
{
duk_get_prop_index(ctx, -1, i); // [dispatcher][hptrList][hptr]
hptr = (void**)duk_get_pointer(ctx, -1);
*hptr = NULL;
duk_pop(ctx); // [dispatcher][hptrList]
}
ILibLinkedList_Clear(eventList);
emitter->totalListeners[0] = 0;
}
return(0);
}
void ILibDuktape_EventEmitter_EmbeddedFinalizer2(ILibHashtable sender, void *Key1, char* Key2, int Key2Len, void *Data, void *user)
{
if (Key1 == NULL)
{
char *name = (char*)ILibMemory_AllocateA(Key2Len + 1);
name[Key2Len] = 0;
memcpy_s(name, Key2Len + 1, Key2, Key2Len);
printf("%s ", name);
}
}
duk_ret_t ILibDuktape_EventEmitter_EmbeddedFinalizer(duk_context *ctx)
{
ILibDuktape_EventEmitter_SetupEmit(ctx, duk_get_heapptr(ctx, 0), "~"); // [emit][this][~]
duk_dup(ctx, 0); // [emit][this][~][self]
if (g_displayFinalizerMessages)
{
printf("+-+- Finalizer Event for: %s [%p] -+-+\n", Duktape_GetStringPropertyValue(ctx, -1, ILibDuktape_OBJID, "UNKNOWN"), duk_get_heapptr(ctx, -1));
if (strcmp(Duktape_GetStringPropertyValue(ctx, -1, ILibDuktape_OBJID, "UNKNOWN"), "UNKNOWN") == 0)
{
ILibDuktape_EventEmitter *emitter = ILibDuktape_EventEmitter_GetEmitter(ctx, -1);
if (emitter != NULL)
{
printf("UNKNOWN: Listeners=%d\n", ILibDuktape_EventEmitter_HasListeners(emitter, "~"));
duk_enum(ctx, -1, DUK_ENUM_OWN_PROPERTIES_ONLY); // [enumerator]
while (duk_next(ctx, -1, 1))
{
printf("Key: %s, Val: %s\n", duk_get_string(ctx, -2), duk_get_string(ctx, -1));// [enumerator][key][val]
duk_pop_2(ctx); // [enumerator]
}
duk_pop(ctx); // ...
printf("Event Names: ");
if (emitter->eventTable != NULL) { ILibHashtable_Enumerate(emitter->eventTable, ILibDuktape_EventEmitter_EmbeddedFinalizer2, NULL); }
printf("\n");
}
}
}
if (duk_pcall_method(ctx, 2) != 0)
{
ILibDuktape_Process_UncaughtExceptionEx(ctx, "Error in Finalizer: [Invalid C function means you forgot to return 0] ");
}
ILibDuktape_EventEmitter *data = ILibDuktape_EventEmitter_GetEmitter(ctx, 0);
if (data == NULL) { return(ILibDuktape_Error(ctx, "Internal Error")); } // This is deadcode, will never occur, but is here because Klockwork thinks this could happen
// We need to clear the Native Dispatcher, while destroying the Hashtable
ILibHashtable_DestroyEx(data->eventTable, ILibDuktape_EventEmitter_FinalizerEx, data);
memset(data, 0, sizeof(ILibDuktape_EventEmitter));
return(0);
}
ILibDuktape_EventEmitter* ILibDuktape_EventEmitter_Create(duk_context *ctx)
{
ILibDuktape_EventEmitter *retVal;
@@ -456,10 +473,8 @@ ILibDuktape_EventEmitter* ILibDuktape_EventEmitter_Create(duk_context *ctx)
retVal->tmpObject = duk_get_heapptr(ctx, -2);
duk_put_prop_string(ctx, -2, ILibDuktape_EventEmitter_Data); // [emitterTmp]
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_EventEmitter_Finalizer);
duk_put_prop_string(ctx, -2, ILibDuktape_EventEmitter_TempObject); // [...parent...]
retVal->ctx = ctx;
retVal->object = duk_get_heapptr(ctx, -1);
retVal->eventTable = ILibHashtable_Create();
@@ -489,6 +504,10 @@ ILibDuktape_EventEmitter* ILibDuktape_EventEmitter_Create(duk_context *ctx)
}
duk_pop(ctx);
ILibDuktape_EventEmitter_CreateEventEx(retVal, "~");
duk_push_c_function(ctx, ILibDuktape_EventEmitter_EmbeddedFinalizer, 1);
duk_set_finalizer(ctx, -2);
return retVal;
}
@@ -505,15 +524,10 @@ duk_ret_t ILibDuktape_EventEmitter_SetEvent(duk_context *ctx)
duk_size_t propNameLen;
ILibDuktape_EventEmitter *data;
ILibLinkedList eventList = NULL;
void **hptr;
void *dispatcher;
int i, count;
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "name"); // [func][name]
duk_get_prop_string(ctx, -1, "eventName"); // [func][name]
propName = (char*)duk_get_lstring(ctx, -1, &propNameLen);
duk_get_prop_string(ctx, -2, ILibDuktape_EventEmitter_DispatcherFunc); // [func][name][dispatcher]
dispatcher = duk_get_heapptr(ctx, -1);
duk_push_this(ctx); // [obj]
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_TempObject); // [this][tmp]
@@ -526,142 +540,20 @@ duk_ret_t ILibDuktape_EventEmitter_SetEvent(duk_context *ctx)
if (duk_is_null_or_undefined(ctx, 0))
{
// NULL was passed, we'll need to clear all listeners.
// Start by setting the Native Dispatcher to NULL, so it appears there are no subscribers
duk_push_heapptr(ctx, dispatcher); // [dispatcher]
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_HPTR_LIST); // [dispatcher][hptrList]
count = (int)duk_get_length(ctx, -1);
for (i = 0; i < count; ++i)
{
duk_get_prop_index(ctx, -1, i); // [dispatcher][hptrList][hptr]
hptr = (void**)duk_get_pointer(ctx, -1);
*hptr = NULL;
duk_pop(ctx); // [dispatcher][hptrList]
}
ILibLinkedList_Clear(eventList);
duk_push_this(ctx); // [obj]
duk_get_prop_string(ctx, -1, "removeAllListeners"); // [obj][removeAll]
duk_swap_top(ctx, -2); // [removeAll][this]
duk_push_string(ctx, propName); // [removeAll][this][name]
duk_call_method(ctx, 1); duk_pop(ctx);
}
else
{
void *callback = duk_require_heapptr(ctx, 0);
ILibDuktape_EventEmitter_HookHandler hookHandler = ILibHashtable_Get(data->eventTable, ILibDuktape_EventEmitter_Hook, propName, (int)propNameLen);
ILibLinkedList_AddTail(eventList, callback);
duk_push_heapptr(ctx, data->tmpObject);
duk_push_heapptr(ctx, callback);
duk_put_prop_string(ctx, -2, Duktape_GetStashKey(callback)); // Save callback to tmpObject so it won't get GC'ed
duk_push_heapptr(ctx, dispatcher); // [dispatcher]
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_HPTR_LIST); // [dispatcher][hptrList]
count = (int)duk_get_length(ctx, -1);
for (i = 0; i < count; ++i)
{
duk_get_prop_index(ctx, -1, i); // [dispatcher][hptrList][hptr]
hptr = (void**)duk_get_pointer(ctx, -1);
*hptr = dispatcher; // Set this, so from Native, it looks like there is a subscriber.
duk_pop(ctx); // [dispatcher][hptrList]
}
if (hookHandler != NULL)
{
hookHandler(data, propName, callback);
}
ILibDuktape_EventEmitter_AddOn(data, propName, duk_get_heapptr(ctx, 0));
}
return 0;
}
duk_ret_t ILibDuktape_EventEmitter_Dispatcher(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
void *self;
int i;
char *name;
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "name"); // [func][name]
name = (char*)duk_get_string(ctx, -1);
duk_get_prop_string(ctx, -2, "this"); // [func][name][this]
self = duk_get_heapptr(ctx, -1);
duk_get_prop_string(ctx, -1, "emit"); // [func][name][this][emitter]
//-------------------------------------------------------------------------------------------------
duk_push_heapptr(ctx, self); // [emitter][this]
duk_push_string(ctx, name); // [emitter][this][name]
for (i = 0; i < nargs; ++i)
{
duk_dup(ctx, i); // [emitter][this][name][...args...]
}
duk_call_method(ctx, nargs + 1); // Exception will bubble up.
return 0;
}
duk_ret_t ILibDuktape_EventEmitter_NativeDispatch(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
char *name;
ILibDuktape_EventEmitter_Handler handler;
void *args;
int i = 0;
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "name"); // [func][name]
name = (char*)duk_get_string(ctx, -1);
duk_get_prop_string(ctx, -2, "handler"); // [func][name][handler]
handler = (ILibDuktape_EventEmitter_Handler)duk_get_pointer(ctx, -1);
duk_push_array(ctx); // [func][name][handler][args]
args = duk_get_heapptr(ctx, -1);
for (i = 0; i < nargs; ++i)
{
duk_dup(ctx, i); // [func][name][handler][args][...arg...]
duk_put_prop_index(ctx, -2, i); // [func][name][handler][args]
}
duk_push_this(ctx);
handler(ctx, duk_get_heapptr(ctx, -1), name, args);
return 0;
}
int ILibDuktape_EventEmitter_AddSink(ILibDuktape_EventEmitter *emitter, char *eventName, ILibDuktape_EventEmitter_Handler handler)
{
ILibLinkedList eventList;
void *func;
duk_push_heapptr(emitter->ctx, emitter->tmpObject); // [tmp]
duk_push_c_function(emitter->ctx, ILibDuktape_EventEmitter_NativeDispatch, DUK_VARARGS); // [tmp][dispatch]
duk_push_string(emitter->ctx, eventName); // [tmp][dispatch][name]
duk_put_prop_string(emitter->ctx, -2, "name"); // [tmp][dispatch]
duk_push_pointer(emitter->ctx, handler); // [tmp][dispatch][nativePtr]
duk_put_prop_string(emitter->ctx, -2, "handler"); // [tmp][dispatch]
func = duk_get_heapptr(emitter->ctx, -1);
eventList = ILibHashtable_Get(emitter->eventTable, NULL, eventName, (int)strnlen_s(eventName, ILibDuktape_EventEmitter_MaxEventNameLen));
if (eventList == NULL) { return 1; }
((int*)ILibLinkedList_GetExtendedMemory(ILibLinkedList_AddTail(eventList, func)))[0] = 2;
emitter->totalListeners[0]++;
duk_put_prop_string(emitter->ctx, -2, Duktape_GetStashKey(func)); // [tmp]
duk_pop(emitter->ctx); // ...
return 0;
}
void ILibDuktape_EventEmitter_RemoveAllEx(ILibHashtable sender, void *Key1, char* Key2, int Key2Len, void *Data, void *user)
{
ILibDuktape_EventEmitter *data = (ILibDuktape_EventEmitter*)user;
if (Key1 == ILibDuktape_EventEmitter_SetterFunc)
{
// If this is not NULL, this is the JavaScript Setter Func
memcpy_s(ILibScratchPad, sizeof(ILibScratchPad), Key2, Key2Len);
ILibScratchPad[Key2Len] = 0;
duk_push_heapptr(data->ctx, Data); // [Setter]
duk_del_prop_string(data->ctx, -1, ILibDuktape_EventEmitter_HPTR_LIST);
duk_push_array(data->ctx); // [Setter][list]
duk_put_prop_string(data->ctx, -2, ILibDuktape_EventEmitter_HPTR_LIST); // [Setter]
duk_pop(data->ctx); // ...
}
}
void ILibDuktape_EventEmitter_RemoveAllListeners(ILibDuktape_EventEmitter *emitter, char *eventName)
{
duk_push_heapptr(emitter->ctx, emitter->object); // [this]
@@ -671,125 +563,45 @@ void ILibDuktape_EventEmitter_RemoveAllListeners(ILibDuktape_EventEmitter *emitt
if (duk_pcall_method(emitter->ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(emitter->ctx, "EventEmitter.removeAllListeners(): "); }
duk_pop(emitter->ctx); // ...
}
void ILibDuktape_EventEmitter_RemoveAll(ILibDuktape_EventEmitter *emitter)
void ILibDuktape_EventEmitter_GetEventCountSink(ILibHashtable sender, void *Key1, char* Key2, int Key2Len, void *Data, void *user)
{
if (emitter->eventTable != NULL) { ILibHashtable_Enumerate(emitter->eventTable, ILibDuktape_EventEmitter_RemoveAllEx, emitter); }
}
void ILibDuktape_EventEmitter_RemoveEventHeapptr(ILibDuktape_EventEmitter *emitter, char *eventName, void **heapptr)
{
int i, count;
void *dispatcher = NULL;
int eventNameLen = (int)strnlen_s(eventName, ILibDuktape_EventEmitter_MaxEventNameLen);
if ((dispatcher = ILibHashtable_Get(emitter->eventTable, ILibDuktape_EventEmitter_SetterFunc, eventName, eventNameLen)) != NULL)
int *count = (int*)user;
if (Key1 == NULL)
{
// This event already exists... Let's hook up the hptr to the existing dispatcher
duk_push_heapptr(emitter->ctx, dispatcher); // [dispatcher]
if (heapptr != NULL)
{
duk_get_prop_string(emitter->ctx, -1, ILibDuktape_EventEmitter_HPTR_LIST); // [dispatcher][hptrList]
count = (int)duk_get_length(emitter->ctx, -1);
for (i = 0; i < count; ++i)
{
duk_get_prop_index(emitter->ctx, -1, i); // [dispatcher][hptrList][hptr]
if (duk_get_pointer(emitter->ctx, -1) == heapptr)
{
duk_pop(emitter->ctx); // [dispatcher][hptrList]
duk_del_prop_index(emitter->ctx, -1, i);
break;
}
duk_pop(emitter->ctx); // [dispatcher][hptrList]
}
duk_pop(emitter->ctx); // [dispatcher]
}
else
{
duk_del_prop_string(emitter->ctx, -1, ILibDuktape_EventEmitter_HPTR_LIST); // [dispatcher]
duk_push_array(emitter->ctx); // [dispatcher][hptrList]
duk_put_prop_string(emitter->ctx, -2, ILibDuktape_EventEmitter_HPTR_LIST); // [dispatcher]
}
duk_pop(emitter->ctx); // ...
++(*count);
}
}
int ILibDuktape_EventEmitter_AddEventHeapptr(ILibDuktape_EventEmitter *emitter, char *eventName, void **heapptr)
int ILibDuktape_EventEmitter_GetEventCount(ILibDuktape_EventEmitter *emitter)
{
ILibLinkedList eventList = NULL;
void *dispatcher = NULL;
int eventNameLen = (int)strnlen_s(eventName, ILibDuktape_EventEmitter_MaxEventNameLen);
if ((dispatcher = ILibHashtable_Get(emitter->eventTable, ILibDuktape_EventEmitter_SetterFunc, eventName, eventNameLen)) != NULL)
{
// This event already exists... Let's hook up the hptr to the existing dispatcher
duk_push_heapptr(emitter->ctx, dispatcher); // [dispatcher]
duk_get_prop_string(emitter->ctx, -1, ILibDuktape_EventEmitter_HPTR_LIST); // [dispatcher][hptrList]
duk_push_pointer(emitter->ctx, heapptr); // [dispatcher][hptrList][hptr]
duk_put_prop_index(emitter->ctx, -2, (duk_uarridx_t)duk_get_length(emitter->ctx, -2)); // [dispatcher][hptrList]
duk_pop_2(emitter->ctx); // ...
int retVal = 0;
if (emitter->eventTable != NULL) { ILibHashtable_Enumerate(emitter->eventTable, ILibDuktape_EventEmitter_GetEventCountSink, &retVal); }
return(retVal);
}
// Now lets check if there was already a subscriber
if ((eventList = ILibHashtable_Get(emitter->eventTable, NULL, eventName, eventNameLen)) != NULL && ILibLinkedList_GetCount(eventList) > 0)
{
*heapptr = dispatcher;
}
return 0;
}
return 1;
}
void ILibDuktape_EventEmitter_CreateEventEx(ILibDuktape_EventEmitter *emitter, char *eventName)
{
void **heapptr;
duk_push_heapptr(emitter->ctx, emitter->tmpObject); // [emitter]
duk_push_object(emitter->ctx); // [emitter][tmp]
duk_push_fixed_buffer(emitter->ctx, sizeof(void*)); // [emitter][tmp][buffer]
heapptr = (void**)Duktape_GetBuffer(emitter->ctx, -1, NULL);
memset((void*)heapptr, 0, sizeof(void*));
duk_put_prop_string(emitter->ctx, -2, "\xFF_buffer"); // [emitter][tmp]
duk_put_prop_string(emitter->ctx, -2, Duktape_GetStashKey(duk_get_heapptr(emitter->ctx, -1))); // [emitter]
duk_pop(emitter->ctx); // ...
ILibDuktape_EventEmitter_CreateEvent(emitter, eventName, heapptr);
}
void ILibDuktape_EventEmitter_CreateEvent(ILibDuktape_EventEmitter *emitter, char *eventName, void **hptr)
{
void *dispatcher = NULL;
int eventNameLen = (int)strnlen_s(eventName, ILibDuktape_EventEmitter_MaxEventNameLen);
if ((dispatcher = ILibHashtable_Get(emitter->eventTable, ILibDuktape_EventEmitter_SetterFunc, eventName, eventNameLen)) != NULL)
if (ILibHashtable_Get(emitter->eventTable, NULL, eventName, eventNameLen) != NULL)
{
// This event already exists... Let's hook up the hptr to the existing dispatcher
duk_push_heapptr(emitter->ctx, dispatcher); // [dispatcher]
duk_get_prop_string(emitter->ctx, -1, ILibDuktape_EventEmitter_HPTR_LIST); // [dispatcher][hptrList]
duk_push_pointer(emitter->ctx, hptr); // [dispatcher][hptrList][hptr]
duk_put_prop_index(emitter->ctx, -2, (duk_uarridx_t)duk_get_length(emitter->ctx, -2)); // [dispatcher][hptrList]
duk_pop_2(emitter->ctx); // ...
// This event already exists...
return;
}
duk_push_heapptr(emitter->ctx, emitter->object); // [obj]
// Create the Property Setter
duk_push_string(emitter->ctx, eventName); // [obj][prop]
duk_push_c_function(emitter->ctx, ILibDuktape_EventEmitter_SetEvent, 1); // [obj][prop][setFunc]
duk_push_string(emitter->ctx, eventName); // [obj][prop][setFunc][name]
duk_put_prop_string(emitter->ctx, -2, "name"); // [obj][prop][setFunc]
// Set some custom properties into the setter func, so we can access it later
duk_push_c_function(emitter->ctx, ILibDuktape_EventEmitter_Dispatcher, DUK_VARARGS); // [obj][prop][setFunc][dispatcher]
dispatcher = duk_get_heapptr(emitter->ctx, -1);
duk_push_heapptr(emitter->ctx, emitter->object); // [obj][prop][setFunc][dispatcher][this]
duk_put_prop_string(emitter->ctx, -2, "this"); // [obj][prop][setFunc][dispatcher]
duk_push_string(emitter->ctx, eventName); // [obj][prop][setFunc][dispatcher][name]
duk_put_prop_string(emitter->ctx, -2, "name"); // [obj][prop][setFunc][dispatcher]
duk_push_array(emitter->ctx); // [obj][prop][setFunc][dispatcher][hptrList]
duk_push_pointer(emitter->ctx, hptr); // [obj][prop][setFunc][dispatcher][hptrList][hptr]
duk_put_prop_index(emitter->ctx, -2, 0); // [obj][prop][setFunc][dispatcher][hptrList]
duk_put_prop_string(emitter->ctx, -2, ILibDuktape_EventEmitter_HPTR_LIST); // [obj][prop][setFunc][dispatcher]
duk_put_prop_string(emitter->ctx, -2, ILibDuktape_EventEmitter_DispatcherFunc); // [obj][prop][setFunc]
duk_put_prop_string(emitter->ctx, -2, "eventName"); // [obj][prop][setFunc]
duk_def_prop(emitter->ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_SETTER); // [obj]
duk_pop(emitter->ctx); // ...
ILibHashtable_Put(emitter->eventTable, NULL, eventName, eventNameLen, ILibLinkedList_CreateEx(sizeof(int)));
ILibHashtable_Put(emitter->eventTable, ILibDuktape_EventEmitter_SetterFunc, eventName, eventNameLen, dispatcher);
}
void *ILibDuktape_EventEmitter_GetDispatcher(ILibDuktape_EventEmitter *emitter, char *eventName)
{
return ILibHashtable_Get(emitter->eventTable, ILibDuktape_EventEmitter_SetterFunc, eventName, (int)strnlen_s(eventName, ILibDuktape_EventEmitter_MaxEventNameLen));
@@ -798,16 +610,13 @@ duk_ret_t ILibDuktape_EventEmitter_Inherits_createEvent(duk_context *ctx)
{
char *name = (char*)duk_require_string(ctx, 0);
ILibDuktape_EventEmitter *emitter;
void **hptr;
duk_push_this(ctx); // [emitterUtils]
duk_get_prop_string(ctx, -1, "emitter"); // [emitterUtils][ptr]
emitter = (ILibDuktape_EventEmitter*)duk_get_pointer(ctx, -1);
duk_pop(ctx); // [emitterUtils]
duk_push_fixed_buffer(ctx, sizeof(void*)); // [emitterUtils][buffer]
hptr = (void**)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, name); // [emitterUtils]
ILibDuktape_EventEmitter_CreateEvent(emitter, name, hptr);
ILibDuktape_EventEmitter_CreateEventEx(emitter, name);
return 0;
}
duk_ret_t ILibDuktape_EventEmitter_Inherits_addMethod(duk_context *ctx)
@@ -878,8 +687,22 @@ duk_ret_t ILibDuktape_EventEmitter_ForwardEvent_Sink(duk_context *ctx)
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);
}
duk_ret_t ILibDuktape_EventEmitter_ForwardEvent_Finalizer(duk_context *ctx)
{
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "fptr"); // [func][fptr]
duk_get_prop_string(ctx, -1, "targetObject"); // [func][fptr][target]
duk_del_prop_string(ctx, -2, "targetObject");
if (g_displayFinalizerMessages) { printf("EventEmitter.Forwarder[%s]: Deleted reference to [%s] RC=%d\n", Duktape_GetStringPropertyValue(ctx, -3, "targetName", "UNKNOWN"), Duktape_GetStringPropertyValue(ctx, -1, ILibDuktape_OBJID, "UNKNOWN"), ILibDuktape_GetReferenceCount(ctx, -1) - 1); }
duk_pop_n(ctx, 3);
if (g_displayFinalizerMessages) { duk_eval_string(ctx, "_debugGC();"); duk_pop(ctx); }
return(0);
}
void ILibDuktape_EventEmitter_ForwardEvent(duk_context *ctx, duk_idx_t eventSourceIndex, char *sourceEventName, duk_idx_t eventTargetIndex, char *targetEventName)
{
void *fptr;
void *target;
duk_dup(ctx, eventTargetIndex); // [targetObject]
target = duk_get_heapptr(ctx, -1);
@@ -889,12 +712,26 @@ void ILibDuktape_EventEmitter_ForwardEvent(duk_context *ctx, duk_idx_t eventSour
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]
fptr = duk_get_heapptr(ctx, -1);
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); // ...
duk_dup(ctx, eventSourceIndex); // [sourceObject]
duk_get_prop_string(ctx, -1, "prependOnceListener"); // [sourceObject][prependOnce]
duk_swap_top(ctx, -2); // [prependOnce][this]
duk_push_string(ctx, "~"); // [prependOnce][this]['~']
duk_push_c_function(ctx, ILibDuktape_EventEmitter_ForwardEvent_Finalizer, DUK_VARARGS); // [prependOnce][this]['~'][func]
duk_push_heapptr(ctx, fptr); // [prependOnce][this]['~'][func][fptr]
duk_put_prop_string(ctx, -2, "fptr"); // [prependOnce][this]['~'][func]
duk_push_string(ctx, targetEventName); // [prependOnce][this]['~'][func][name]
duk_put_prop_string(ctx, -2, "targetName"); // [prependOnce][this]['~'][func]
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "EventEmitter_ForwardEvent_SetFinalizer(): "); }
duk_pop(ctx); // ...
}
int ILibDuktape_EventEmitter_AddOnEx(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func)
{

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,471 @@
/*
* Duktape 1.x compatible module loading framework
*/
#include "duktape.h"
#include "duk_module_duktape.h"
/* (v)snprintf() is missing before MSVC 2015. Note that _(v)snprintf() does
* NOT NUL terminate on truncation, but that's OK here.
* http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
*/
#if defined(_MSC_VER) && (_MSC_VER < 1900)
#define snprintf _snprintf
#endif
#if 0 /* Enable manually */
#define DUK__ASSERT(x) do { \
if (!(x)) { \
fprintf(stderr, "ASSERTION FAILED at %s:%d: " #x "\n", __FILE__, __LINE__); \
fflush(stderr); \
} \
} while (0)
#define DUK__ASSERT_TOP(ctx,val) do { \
DUK__ASSERT(duk_get_top((ctx)) == (val)); \
} while (0)
#else
#define DUK__ASSERT(x) do { (void) (x); } while (0)
#define DUK__ASSERT_TOP(ctx,val) do { (void) ctx; (void) (val); } while (0)
#endif
static void duk__resolve_module_id(duk_context *ctx, const char *req_id, const char *mod_id) {
duk_uint8_t buf[DUK_COMMONJS_MODULE_ID_LIMIT];
duk_uint8_t *p;
duk_uint8_t *q;
duk_uint8_t *q_last; /* last component */
duk_int_t int_rc;
DUK__ASSERT(req_id != NULL);
/* mod_id may be NULL */
/*
* A few notes on the algorithm:
*
* - Terms are not allowed to begin with a period unless the term
* is either '.' or '..'. This simplifies implementation (and
* is within CommonJS modules specification).
*
* - There are few output bound checks here. This is on purpose:
* the resolution input is length checked and the output is never
* longer than the input. The resolved output is written directly
* over the input because it's never longer than the input at any
* point in the algorithm.
*
* - Non-ASCII characters are processed as individual bytes and
* need no special treatment. However, U+0000 terminates the
* algorithm; this is not an issue because U+0000 is not a
* desirable term character anyway.
*/
/*
* Set up the resolution input which is the requested ID directly
* (if absolute or no current module path) or with current module
* ID prepended (if relative and current module path exists).
*
* Suppose current module is 'foo/bar' and relative path is './quux'.
* The 'bar' component must be replaced so the initial input here is
* 'foo/bar/.././quux'.
*/
if (mod_id != NULL && req_id[0] == '.') {
int_rc = snprintf((char *) buf, sizeof(buf), "%s/../%s", mod_id, req_id);
} else {
int_rc = snprintf((char *) buf, sizeof(buf), "%s", req_id);
}
if (int_rc >= (duk_int_t) sizeof(buf) || int_rc < 0) {
/* Potentially truncated, NUL not guaranteed in any case.
* The (int_rc < 0) case should not occur in practice.
*/
goto resolve_error;
}
DUK__ASSERT(strlen((const char *) buf) < sizeof(buf)); /* at most sizeof(buf) - 1 */
/*
* Resolution loop. At the top of the loop we're expecting a valid
* term: '.', '..', or a non-empty identifier not starting with a period.
*/
p = buf;
q = buf;
for (;;) {
duk_uint_fast8_t c;
/* Here 'p' always points to the start of a term.
*
* We can also unconditionally reset q_last here: if this is
* the last (non-empty) term q_last will have the right value
* on loop exit.
*/
DUK__ASSERT(p >= q); /* output is never longer than input during resolution */
q_last = q;
c = *p++;
if (c == 0) {
goto resolve_error;
} else if (c == '.') {
c = *p++;
if (c == '/') {
/* Term was '.' and is eaten entirely (including dup slashes). */
goto eat_dup_slashes;
}
if (c == '.' && *p == '/') {
/* Term was '..', backtrack resolved name by one component.
* q[-1] = previous slash (or beyond start of buffer)
* q[-2] = last char of previous component (or beyond start of buffer)
*/
p++; /* eat (first) input slash */
DUK__ASSERT(q >= buf);
if (q == buf) {
goto resolve_error;
}
DUK__ASSERT(*(q - 1) == '/');
q--; /* Backtrack to last output slash (dups already eliminated). */
for (;;) {
/* Backtrack to previous slash or start of buffer. */
DUK__ASSERT(q >= buf);
if (q == buf) {
break;
}
if (*(q - 1) == '/') {
break;
}
q--;
}
goto eat_dup_slashes;
}
goto resolve_error;
} else if (c == '/') {
/* e.g. require('/foo'), empty terms not allowed */
goto resolve_error;
} else {
for (;;) {
/* Copy term name until end or '/'. */
*q++ = c;
c = *p++;
if (c == 0) {
/* This was the last term, and q_last was
* updated to match this term at loop top.
*/
goto loop_done;
} else if (c == '/') {
*q++ = '/';
break;
} else {
/* write on next loop */
}
}
}
eat_dup_slashes:
for (;;) {
/* eat dup slashes */
c = *p;
if (c != '/') {
break;
}
p++;
}
}
loop_done:
/* Output #1: resolved absolute name. */
DUK__ASSERT(q >= buf);
duk_push_lstring(ctx, (const char *) buf, (size_t) (q - buf));
/* Output #2: last component name. */
DUK__ASSERT(q >= q_last);
DUK__ASSERT(q_last >= buf);
duk_push_lstring(ctx, (const char *) q_last, (size_t) (q - q_last));
return;
resolve_error:
(void) duk_type_error(ctx, "cannot resolve module id: %s", (const char *) req_id);
}
/* Stack indices for better readability. */
#define DUK__IDX_REQUESTED_ID 0 /* module id requested */
#define DUK__IDX_REQUIRE 1 /* current require() function */
#define DUK__IDX_REQUIRE_ID 2 /* the base ID of the current require() function, resolution base */
#define DUK__IDX_RESOLVED_ID 3 /* resolved, normalized absolute module ID */
#define DUK__IDX_LASTCOMP 4 /* last component name in resolved path */
#define DUK__IDX_DUKTAPE 5 /* Duktape object */
#define DUK__IDX_MODLOADED 6 /* Duktape.modLoaded[] module cache */
#define DUK__IDX_UNDEFINED 7 /* 'undefined', artifact of lookup */
#define DUK__IDX_FRESH_REQUIRE 8 /* new require() function for module, updated resolution base */
#define DUK__IDX_EXPORTS 9 /* default exports table */
#define DUK__IDX_MODULE 10 /* module object containing module.exports, etc */
static duk_ret_t duk__require(duk_context *ctx) {
const char *str_req_id; /* requested identifier */
const char *str_mod_id; /* require.id of current module */
duk_int_t pcall_rc;
/* NOTE: we try to minimize code size by avoiding unnecessary pops,
* so the stack looks a bit cluttered in this function. DUK__ASSERT_TOP()
* assertions are used to ensure stack configuration is correct at each
* step.
*/
/*
* Resolve module identifier into canonical absolute form.
*/
str_req_id = duk_require_string(ctx, DUK__IDX_REQUESTED_ID);
duk_push_current_function(ctx);
duk_get_prop_string(ctx, -1, "id");
str_mod_id = duk_get_string(ctx, DUK__IDX_REQUIRE_ID); /* ignore non-strings */
duk__resolve_module_id(ctx, str_req_id, str_mod_id);
str_req_id = NULL;
str_mod_id = NULL;
/* [ requested_id require require.id resolved_id last_comp ] */
DUK__ASSERT_TOP(ctx, DUK__IDX_LASTCOMP + 1);
/*
* Cached module check.
*
* If module has been loaded or its loading has already begun without
* finishing, return the same cached value (module.exports). The
* value is registered when module load starts so that circular
* references can be supported to some extent.
*/
duk_push_global_stash(ctx);
duk_get_prop_string(ctx, -1, "\xff" "module:Duktape");
duk_remove(ctx, -2); /* Lookup stashed, original 'Duktape' object. */
duk_get_prop_string(ctx, DUK__IDX_DUKTAPE, "modLoaded"); /* Duktape.modLoaded */
duk_require_type_mask(ctx, DUK__IDX_MODLOADED, DUK_TYPE_MASK_OBJECT);
DUK__ASSERT_TOP(ctx, DUK__IDX_MODLOADED + 1);
duk_dup(ctx, DUK__IDX_RESOLVED_ID);
if (duk_get_prop(ctx, DUK__IDX_MODLOADED)) {
/* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded Duktape.modLoaded[id] ] */
duk_get_prop_string(ctx, -1, "exports"); /* return module.exports */
return 1;
}
DUK__ASSERT_TOP(ctx, DUK__IDX_UNDEFINED + 1);
/* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined ] */
/*
* Module not loaded (and loading not started previously).
*
* Create a new require() function with 'id' set to resolved ID
* of module being loaded. Also create 'exports' and 'module'
* tables but don't register exports to the loaded table yet.
* We don't want to do that unless the user module search callbacks
* succeeds in finding the module.
*/
/* Fresh require: require.id is left configurable (but not writable)
* so that is not easy to accidentally tweak it, but it can still be
* done with Object.defineProperty().
*
* XXX: require.id could also be just made non-configurable, as there
* is no practical reason to touch it (at least from Ecmascript code).
*/
duk_push_c_function(ctx, duk__require, 1 /*nargs*/);
duk_push_string(ctx, "name");
duk_push_string(ctx, "require");
duk_def_prop(ctx, DUK__IDX_FRESH_REQUIRE, DUK_DEFPROP_HAVE_VALUE); /* not writable, not enumerable, not configurable */
duk_push_string(ctx, "id");
duk_dup(ctx, DUK__IDX_RESOLVED_ID);
duk_def_prop(ctx, DUK__IDX_FRESH_REQUIRE, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_SET_CONFIGURABLE); /* a fresh require() with require.id = resolved target module id */
/* Module table:
* - module.exports: initial exports table (may be replaced by user)
* - module.id is non-writable and non-configurable, as the CommonJS
* spec suggests this if possible
* - module.filename: not set, defaults to resolved ID if not explicitly
* set by modSearch() (note capitalization, not .fileName, matches Node.js)
* - module.name: not set, defaults to last component of resolved ID if
* not explicitly set by modSearch()
*/
duk_push_object(ctx); /* exports */
duk_push_object(ctx); /* module */
duk_push_string(ctx, "exports");
duk_dup(ctx, DUK__IDX_EXPORTS);
duk_def_prop(ctx, DUK__IDX_MODULE, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_SET_WRITABLE | DUK_DEFPROP_SET_CONFIGURABLE); /* module.exports = exports */
duk_push_string(ctx, "id");
duk_dup(ctx, DUK__IDX_RESOLVED_ID); /* resolved id: require(id) must return this same module */
duk_def_prop(ctx, DUK__IDX_MODULE, DUK_DEFPROP_HAVE_VALUE); /* module.id = resolved_id; not writable, not enumerable, not configurable */
duk_compact(ctx, DUK__IDX_MODULE); /* module table remains registered to modLoaded, minimize its size */
DUK__ASSERT_TOP(ctx, DUK__IDX_MODULE + 1);
/* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined fresh_require exports module ] */
/* Register the module table early to modLoaded[] so that we can
* support circular references even in modSearch(). If an error
* is thrown, we'll delete the reference.
*/
duk_dup(ctx, DUK__IDX_RESOLVED_ID);
duk_dup(ctx, DUK__IDX_MODULE);
duk_put_prop(ctx, DUK__IDX_MODLOADED); /* Duktape.modLoaded[resolved_id] = module */
/*
* Call user provided module search function and build the wrapped
* module source code (if necessary). The module search function
* can be used to implement pure Ecmacsript, pure C, and mixed
* Ecmascript/C modules.
*
* The module search function can operate on the exports table directly
* (e.g. DLL code can register values to it). It can also return a
* string which is interpreted as module source code (if a non-string
* is returned the module is assumed to be a pure C one). If a module
* cannot be found, an error must be thrown by the user callback.
*
* Because Duktape.modLoaded[] already contains the module being
* loaded, circular references for C modules should also work
* (although expected to be quite rare).
*/
duk_push_string(ctx, "(function(require,exports,module){");
/* Duktape.modSearch(resolved_id, fresh_require, exports, module). */
duk_get_prop_string(ctx, DUK__IDX_DUKTAPE, "modSearch"); /* Duktape.modSearch */
duk_dup(ctx, DUK__IDX_RESOLVED_ID);
duk_dup(ctx, DUK__IDX_FRESH_REQUIRE);
duk_dup(ctx, DUK__IDX_EXPORTS);
duk_dup(ctx, DUK__IDX_MODULE); /* [ ... Duktape.modSearch resolved_id last_comp fresh_require exports module ] */
pcall_rc = duk_pcall(ctx, 4 /*nargs*/); /* -> [ ... source ] */
DUK__ASSERT_TOP(ctx, DUK__IDX_MODULE + 3);
if (pcall_rc != DUK_EXEC_SUCCESS) {
/* Delete entry in Duktape.modLoaded[] and rethrow. */
goto delete_rethrow;
}
/* If user callback did not return source code, module loading
* is finished (user callback initialized exports table directly).
*/
if (!duk_is_string(ctx, -1)) {
/* User callback did not return source code, so module loading
* is finished: just update modLoaded with final module.exports
* and we're done.
*/
goto return_exports;
}
/* Finish the wrapped module source. Force module.filename as the
* function .fileName so it gets set for functions defined within a
* module. This also ensures loggers created within the module get
* the module ID (or overridden filename) as their default logger name.
* (Note capitalization: .filename matches Node.js while .fileName is
* used elsewhere in Duktape.)
*/
duk_push_string(ctx, "\n})"); /* Newline allows module last line to contain a // comment. */
duk_concat(ctx, 3);
if (!duk_get_prop_string(ctx, DUK__IDX_MODULE, "filename")) {
/* module.filename for .fileName, default to resolved ID if
* not present.
*/
duk_pop(ctx);
duk_dup(ctx, DUK__IDX_RESOLVED_ID);
}
pcall_rc = duk_pcompile(ctx, DUK_COMPILE_EVAL);
if (pcall_rc != DUK_EXEC_SUCCESS) {
goto delete_rethrow;
}
pcall_rc = duk_pcall(ctx, 0); /* -> eval'd function wrapper (not called yet) */
if (pcall_rc != DUK_EXEC_SUCCESS) {
goto delete_rethrow;
}
/* Module has now evaluated to a wrapped module function. Force its
* .name to match module.name (defaults to last component of resolved
* ID) so that it is shown in stack traces too. Note that we must not
* introduce an actual name binding into the function scope (which is
* usually the case with a named function) because it would affect the
* scope seen by the module and shadow accesses to globals of the same name.
* This is now done by compiling the function as anonymous and then forcing
* its .name without setting a "has name binding" flag.
*/
duk_push_string(ctx, "name");
if (!duk_get_prop_string(ctx, DUK__IDX_MODULE, "name")) {
/* module.name for .name, default to last component if
* not present.
*/
duk_pop(ctx);
duk_dup(ctx, DUK__IDX_LASTCOMP);
}
duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_FORCE);
/*
* Call the wrapped module function.
*
* Use a protected call so that we can update Duktape.modLoaded[resolved_id]
* even if the module throws an error.
*/
/* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined fresh_require exports module mod_func ] */
DUK__ASSERT_TOP(ctx, DUK__IDX_MODULE + 2);
duk_dup(ctx, DUK__IDX_EXPORTS); /* exports (this binding) */
duk_dup(ctx, DUK__IDX_FRESH_REQUIRE); /* fresh require (argument) */
duk_get_prop_string(ctx, DUK__IDX_MODULE, "exports"); /* relookup exports from module.exports in case it was changed by modSearch */
duk_dup(ctx, DUK__IDX_MODULE); /* module (argument) */
DUK__ASSERT_TOP(ctx, DUK__IDX_MODULE + 6);
/* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined fresh_require exports module mod_func exports fresh_require exports module ] */
pcall_rc = duk_pcall_method(ctx, 3 /*nargs*/);
if (pcall_rc != DUK_EXEC_SUCCESS) {
/* Module loading failed. Node.js will forget the module
* registration so that another require() will try to load
* the module again. Mimic that behavior.
*/
goto delete_rethrow;
}
/* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined fresh_require exports module result(ignored) ] */
DUK__ASSERT_TOP(ctx, DUK__IDX_MODULE + 2);
/* fall through */
return_exports:
duk_get_prop_string(ctx, DUK__IDX_MODULE, "exports");
duk_compact(ctx, -1); /* compact the exports table */
return 1; /* return module.exports */
delete_rethrow:
duk_dup(ctx, DUK__IDX_RESOLVED_ID);
duk_del_prop(ctx, DUK__IDX_MODLOADED); /* delete Duktape.modLoaded[resolved_id] */
(void) duk_throw(ctx); /* rethrow original error */
return 0; /* not reachable */
}
void duk_module_duktape_init(duk_context *ctx) {
/* Stash 'Duktape' in case it's modified. */
duk_push_global_stash(ctx);
duk_get_global_string(ctx, "Duktape");
duk_put_prop_string(ctx, -2, "\xff" "module:Duktape");
duk_pop(ctx);
/* Register `require` as a global function. */
duk_eval_string(ctx,
"(function(req){"
"var D=Object.defineProperty;"
"D(req,'name',{value:'require'});"
"D(this,'require',{value:req,writable:true,configurable:true});"
"D(Duktape,'modLoaded',{value:Object.create(null),writable:true,configurable:true});"
"})");
duk_push_c_function(ctx, duk__require, 1 /*nargs*/);
duk_call(ctx, 1);
duk_pop(ctx);
}
#undef DUK__ASSERT
#undef DUK__ASSERT_TOP
#undef DUK__IDX_REQUESTED_ID
#undef DUK__IDX_REQUIRE
#undef DUK__IDX_REQUIRE_ID
#undef DUK__IDX_RESOLVED_ID
#undef DUK__IDX_LASTCOMP
#undef DUK__IDX_DUKTAPE
#undef DUK__IDX_MODLOADED
#undef DUK__IDX_UNDEFINED
#undef DUK__IDX_FRESH_REQUIRE
#undef DUK__IDX_EXPORTS
#undef DUK__IDX_MODULE

View File

@@ -0,0 +1,14 @@
#if !defined(DUK_MODULE_DUKTAPE_H_INCLUDED)
#define DUK_MODULE_DUKTAPE_H_INCLUDED
#include "duktape.h"
/* Maximum length of CommonJS module identifier to resolve. Length includes
* both current module ID, requested (possibly relative) module ID, and a
* slash in between.
*/
#define DUK_COMMONJS_MODULE_ID_LIMIT 256
extern void duk_module_duktape_init(duk_context *ctx);
#endif /* DUK_MODULE_DUKTAPE_H_INCLUDED */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff