1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2026-01-07 19:13:20 +00:00

First commit of MeshAgent for MeshCentral

This commit is contained in:
Ylian Saint-Hilaire
2017-10-12 14:28:03 -07:00
commit 75d86eb4c8
349 changed files with 210459 additions and 0 deletions

View File

@@ -0,0 +1,265 @@
/*
Copyright 2006 - 2017 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>
#endif
#include "microstack/ILibParsers.h"
#include "microstack/ILibAsyncServerSocket.h"
#include "ILibAsyncSocket_Duktape.h"
#include "ILibDuktape_Helpers.h"
extern char *Duktape_GetStashKey(void* value);
extern char* Duktape_GetBuffer(duk_context *ctx, duk_idx_t i, duk_size_t *bufLen);
duk_idx_t ILibAsyncSocket_Duktape_PUSH_AsyncSocketModule(duk_context *ctx, ILibAsyncSocket_SocketModule module);
typedef struct ILibAsyncSocket_Duktape_Bindings
{
duk_context *context;
void *OnData;
void *OnConnect;
void *OnDisconnect;
void *OnSendOK;
}ILibAsyncSocket_Duktape_Bindings;
void ILibAsyncSocket_Duktape_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffer, int *p_beginPointer, int endPointer, ILibAsyncSocket_OnInterrupt* OnInterrupt, void **user, int *PAUSE)
{
ILibAsyncSocket_Duktape_Bindings *bindings = (ILibAsyncSocket_Duktape_Bindings*)((ILibChain_Link*)socketModule)->ExtraMemoryPtr;
if (bindings->OnData == NULL) { *p_beginPointer = endPointer; return; }
duk_push_heapptr(bindings->context, bindings->OnData); // [ptr]
ILibAsyncSocket_Duktape_PUSH_AsyncSocketModule(bindings->context, socketModule); // [ptr][obj]
if (duk_has_prop_string(bindings->context, -1, "BufferPtr"))
{
duk_get_prop_string(bindings->context, -1, "BufferPtr"); // [ptr][obj][buffer]
}
else
{
duk_push_external_buffer(bindings->context); // [ptr][obj][buffer]
duk_dup(bindings->context, -1); // [ptr][obj][buffer][buffer]
duk_put_prop_string(bindings->context, -3, "BufferPtr"); // [ptr][obj][buffer]
}
duk_config_buffer(bindings->context, -1, buffer + *p_beginPointer, endPointer);
duk_push_int(bindings->context, endPointer); // [ptr][obj][buffer][endPointer]
if (duk_pcall(bindings->context, 3) == 0) // [retVal]
{
if (duk_is_undefined(bindings->context, -1)) { *p_beginPointer = endPointer; duk_pop(bindings->context); }
else if (duk_is_number(bindings->context, -1))
{
int val = duk_to_int(bindings->context, -1);
if (val < 0) { *PAUSE = 1; }
else { *p_beginPointer = val; }
duk_pop(bindings->context); // ...
}
}
else
{
ILibDuktape_Process_UncaughtException(bindings->context);
duk_pop(bindings->context);
}
}
void ILibAsyncSocket_Duktape_OnConnect(ILibAsyncSocket_SocketModule socketModule, int Connected, void *user)
{
ILibAsyncSocket_Duktape_Bindings *bindings = (ILibAsyncSocket_Duktape_Bindings*)((ILibChain_Link*)socketModule)->ExtraMemoryPtr;
if (bindings->OnConnect != NULL)
{
duk_push_heapptr(bindings->context, bindings->OnConnect); // [ptr]
ILibAsyncSocket_Duktape_PUSH_AsyncSocketModule(bindings->context, socketModule); // [ptr][obj]
duk_push_int(bindings->context, Connected); // [ptr][obj][Connected]
if (duk_pcall(bindings->context, 2) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(bindings->context);
}
duk_pop(bindings->context); // ...
}
}
void ILibAsyncSocket_Duktape_OnDisconnect(ILibAsyncSocket_SocketModule socketModule, void *user)
{
ILibAsyncSocket_Duktape_Bindings *bindings = (ILibAsyncSocket_Duktape_Bindings*)((ILibChain_Link*)socketModule)->ExtraMemoryPtr;
if (bindings->OnDisconnect != NULL)
{
duk_push_heapptr(bindings->context, bindings->OnDisconnect); // [ptr]
ILibAsyncSocket_Duktape_PUSH_AsyncSocketModule(bindings->context, socketModule); // [ptr][obj]
if (duk_pcall(bindings->context, 1) != 0) // [...]
{
ILibDuktape_Process_UncaughtException(bindings->context);
}
duk_pop(bindings->context); //
}
}
void ILibAsyncSocket_Duktape_OnSendOK(ILibAsyncSocket_SocketModule socketModule, void *user)
{
ILibAsyncSocket_Duktape_Bindings *bindings = (ILibAsyncSocket_Duktape_Bindings*)((ILibChain_Link*)socketModule)->ExtraMemoryPtr;
if (bindings->OnSendOK != NULL)
{
duk_push_heapptr(bindings->context, bindings->OnSendOK); // [ptr]
ILibAsyncSocket_Duktape_PUSH_AsyncSocketModule(bindings->context, socketModule); // [ptr][obj]
if (duk_pcall(bindings->context, 1) != 0) // [...]
{
ILibDuktape_Process_UncaughtException(bindings->context);
}
duk_pop(bindings->context); //
}
}
duk_ret_t ILibAsyncSocket_Duktape_Create(duk_context *ctx)
{
// ILibCreateAsyncSocketModuleWithMemory(void *Chain, int initialBufferSize, ILibAsyncSocket_OnData OnData, ILibAsyncSocket_OnConnect OnConnect, ILibAsyncSocket_OnDisconnect OnDisconnect, ILibAsyncSocket_OnSendOK OnSendOK, int UserMappedMemorySize)
void *chain;
int initialBufferSize = duk_require_int(ctx, 0);
void *OnData = duk_is_null(ctx, 1) ? NULL : duk_require_heapptr(ctx, 1);
void *OnConnect = duk_is_null(ctx, 2) ? NULL : duk_require_heapptr(ctx, 2);
void *OnDisconnect = duk_is_null(ctx, 3) ? NULL : duk_require_heapptr(ctx, 3);
void *OnSendOK = duk_is_null(ctx, 4) ? NULL : duk_require_heapptr(ctx, 4);
ILibAsyncSocket_SocketModule module;
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "chain"); // [func][chain]
chain = duk_to_pointer(ctx, -1);
module = ILibCreateAsyncSocketModuleWithMemory(chain, initialBufferSize, ILibAsyncSocket_Duktape_OnData, ILibAsyncSocket_Duktape_OnConnect, ILibAsyncSocket_Duktape_OnDisconnect, ILibAsyncSocket_Duktape_OnSendOK, sizeof(ILibAsyncSocket_Duktape_Bindings));
((ILibAsyncSocket_Duktape_Bindings*)((ILibChain_Link*)module)->ExtraMemoryPtr)->context = ctx;
((ILibAsyncSocket_Duktape_Bindings*)((ILibChain_Link*)module)->ExtraMemoryPtr)->OnConnect = OnConnect;
((ILibAsyncSocket_Duktape_Bindings*)((ILibChain_Link*)module)->ExtraMemoryPtr)->OnData = OnData;
((ILibAsyncSocket_Duktape_Bindings*)((ILibChain_Link*)module)->ExtraMemoryPtr)->OnDisconnect = OnDisconnect;
((ILibAsyncSocket_Duktape_Bindings*)((ILibChain_Link*)module)->ExtraMemoryPtr)->OnSendOK = OnSendOK;
ILibAsyncSocket_Duktape_PUSH_AsyncSocketModule(ctx, module); // [obj]
duk_dup(ctx, 1); // [obj][OnData]
duk_put_prop_string(ctx, -2, "OnDataPtr"); // [obj]
duk_dup(ctx, 2); // [obj][OnConnect]
duk_put_prop_string(ctx, -2, "OnConnectPtr"); // [obj]
duk_dup(ctx, 3); // [obj][OnDisconnect]
duk_put_prop_string(ctx, -2, "OnDisconnectPtr"); // [obj]
duk_dup(ctx, 4); // [obj][OnSendOK]
duk_put_prop_string(ctx, -2, "OnSendOKPtr"); // [obj]
return 1;
}
duk_ret_t ILibAsyncSocket_Duktape_Send(duk_context *ctx)
{
ILibAsyncSocket_SocketModule module;
char *buffer = Duktape_GetBuffer(ctx, 0, NULL);
int bufferLen = duk_require_int(ctx, 1);
ILibAsyncSocket_SendStatus retVal;
duk_push_this(ctx); // [obj]
duk_get_prop_string(ctx, -1, "ModulePtr"); // [obj][ptr]
module = duk_to_pointer(ctx, -1);
retVal = ILibAsyncSocket_Send(module, buffer, bufferLen, ILibAsyncSocket_MemoryOwnership_USER);
duk_push_int(ctx, retVal);
return 1;
}
duk_ret_t ILibAsyncSocket_Duktape_Disconnect(duk_context *ctx)
{
ILibAsyncSocket_SocketModule module;
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "ModulePtr");
module = duk_to_pointer(ctx, -1);
ILibAsyncSocket_Disconnect(module);
return 0;
}
duk_ret_t ILibAsyncSocket_Duktape_ConnectTo(duk_context *ctx)
{
char *localAddress;
int localPort;
char *remoteAddress;
int remotePort;
struct sockaddr_in6 localAddr;
struct sockaddr_in6 remoteAddr;
ILibAsyncSocket_SocketModule module;
if (!duk_has_prop_string(ctx, 0, "IPAddress")) { duk_push_string(ctx, "Missing [Local] IPAddress Property"); duk_throw(ctx); return DUK_RET_ERROR; }
if (!duk_has_prop_string(ctx, 0, "Port")) { duk_push_string(ctx, "Missing [Local] Port Property"); duk_throw(ctx); return DUK_RET_ERROR; }
if (!duk_has_prop_string(ctx, 1, "IPAddress")) { duk_push_string(ctx, "Missing [Remote] IPAddress Property"); duk_throw(ctx); return DUK_RET_ERROR; }
if (!duk_has_prop_string(ctx, 1, "Port")) { duk_push_string(ctx, "Missing [Remote] Port Property"); duk_throw(ctx); return DUK_RET_ERROR; }
duk_get_prop_string(ctx, 0, "IPAddress");
localAddress = (char*)duk_to_string(ctx, -1);
duk_get_prop_string(ctx, 0, "Port");
localPort = duk_to_int(ctx, -1);
duk_get_prop_string(ctx, 1, "IPAddress");
remoteAddress = (char*)duk_to_string(ctx, -1);
duk_get_prop_string(ctx, 1, "Port");
remotePort = duk_to_int(ctx, -1);
memset(&localAddr, 0, sizeof(struct sockaddr_in6));
memset(&remoteAddr, 0, sizeof(struct sockaddr_in6));
((struct sockaddr_in*)&localAddr)->sin_family = AF_INET;
((struct sockaddr_in*)&localAddr)->sin_port = htons(localPort);
ILibInet_pton(AF_INET, localAddress, &(((struct sockaddr_in*)&localAddr)->sin_addr));
((struct sockaddr_in*)&remoteAddr)->sin_family = AF_INET;
((struct sockaddr_in*)&remoteAddr)->sin_port = htons(remotePort);
ILibInet_pton(AF_INET, remoteAddress, &(((struct sockaddr_in*)&remoteAddr)->sin_addr));
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "ModulePtr");
module = duk_to_pointer(ctx, -1);
ILibAsyncSocket_ConnectTo(module, (struct sockaddr*)&localAddr, (struct sockaddr*)&remoteAddr, NULL, NULL);
return 0;
}
duk_idx_t ILibAsyncSocket_Duktape_PUSH_AsyncSocketModule(duk_context *ctx, ILibAsyncSocket_SocketModule module)
{
char* key = Duktape_GetStashKey(module);
duk_push_heap_stash(ctx); // [stash]
if (duk_has_prop_string(ctx, -1, key))
{
duk_get_prop_string(ctx, -1, key); // [stash][obj]
duk_swap_top(ctx, -2); // [obj][stash]
duk_pop(ctx); // [obj]
return duk_get_top_index(ctx);
}
duk_push_object(ctx); // [stash][obj]
duk_push_pointer(ctx, module); // [stash][obj][pointer]
duk_put_prop_string(ctx, -2, "ModulePtr"); // [stash][obj]
duk_dup(ctx, -1); // [stash][obj][obj]
duk_put_prop_string(ctx, -3, key); // [stash][obj]
duk_swap_top(ctx, -2); // [obj][stash]
duk_pop(ctx); // [obj]
duk_push_c_function(ctx, ILibAsyncSocket_Duktape_Send, 2); // [obj][func]
duk_put_prop_string(ctx, -2, "Send"); // [obj]
duk_push_c_function(ctx, ILibAsyncSocket_Duktape_Disconnect, 0); // [obj][func]
duk_put_prop_string(ctx, -2, "Disconnect"); // [obj]
duk_push_c_function(ctx, ILibAsyncSocket_Duktape_ConnectTo, 2);
duk_put_prop_string(ctx, -2, "ConnectTo");
return duk_get_top_index(ctx);
}
void ILibAsyncSocket_DukTape_Init(duk_context * ctx, void * chain)
{
duk_push_global_object(ctx); // [Global]
duk_push_c_function(ctx, ILibAsyncSocket_Duktape_Create, 5); // [Global][func]
duk_push_pointer(ctx, chain); // [Global][func][chain]
duk_put_prop_string(ctx, -2, "chain"); // [Global][func]
duk_put_prop_string(ctx, -2, "ILibAsyncSocket_Create"); // [Global]
duk_pop(ctx); //
}

View File

@@ -0,0 +1,25 @@
/*
Copyright 2006 - 2017 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 ___ILIBASYNCSOCKETDUKTAPE___
#define ___ILIBASYNCSOCKETDUKTAPE___
#include "duktape.h"
void ILibAsyncSocket_DukTape_Init(duk_context *ctx, void * chain);
#endif

View File

@@ -0,0 +1,227 @@
/*
Copyright 2006 - 2017 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>
#endif
#include "ILibDuktapeModSearch.h"
#include "microstack/ILibParsers.h"
#include "microscript/ILibDuktape_Helpers.h"
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(_MINCORE)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif
#define ILibDuktape_ModSearch_ModuleFile "0xFF"
int ILibDuktape_ModSearch_AddModule(duk_context *ctx, char *id, char *module, int moduleLen)
{
ILibHashtable table = NULL;
int idLen = (int)strnlen_s(id, 1024);
duk_push_heap_stash(ctx); // [stash]
if (duk_has_prop_string(ctx, -1, "ModSearchTable"))
{
duk_get_prop_string(ctx, -1, "ModSearchTable"); // [stash][ptr]
table = (ILibHashtable)duk_to_pointer(ctx, -1);
duk_pop(ctx); // [stash]
}
else
{
table = ILibHashtable_Create();
duk_push_pointer(ctx, table); // [stash][ptr]
duk_put_prop_string(ctx, -2, "ModSearchTable"); // [stash]
}
duk_pop(ctx); // ...
if (ILibHashtable_Get(table, NULL, id, idLen) != NULL || ILibHashtable_Get(table, ILibDuktape_ModSearch_ModuleFile, id, idLen) != NULL) { return 1; }
char *newModule = (char*)ILibDuktape_Memory_Alloc(ctx, moduleLen+1);
memcpy_s(newModule, moduleLen + 1, module, moduleLen);
newModule[moduleLen] = 0;
ILibHashtable_Put(table, ILibDuktape_ModSearch_ModuleFile, id, idLen, newModule);
return 0;
}
int ILibDuktape_ModSearch_AddHandler(duk_context *ctx, char *id, ILibDuktape_ModSearch_PUSH_Object handler)
{
ILibHashtable table = NULL;
int idLen = (int)strnlen_s(id, 1024);
duk_push_heap_stash(ctx); // [stash]
if (duk_has_prop_string(ctx, -1, "ModSearchTable"))
{
duk_get_prop_string(ctx, -1, "ModSearchTable"); // [stash][ptr]
table = (ILibHashtable)duk_to_pointer(ctx, -1);
duk_pop(ctx); // [stash]
}
else
{
table = ILibHashtable_Create();
duk_push_pointer(ctx, table); // [stash][ptr]
duk_put_prop_string(ctx, -2, "ModSearchTable"); // [stash]
}
duk_pop(ctx); // ...
if (ILibHashtable_Get(table, NULL, id, idLen) != NULL || ILibHashtable_Get(table, ILibDuktape_ModSearch_ModuleFile, id, idLen) != NULL) { return 1; }
ILibHashtable_Put(table, NULL, id, idLen, handler);
return 0;
}
duk_ret_t mod_Search_Files(duk_context *ctx, char* id)
{
char fileName[255];
char *data;
int dataLen;
sprintf_s(fileName, sizeof(fileName), "%s.js", id);
dataLen = ILibReadFileFromDiskEx(&data, fileName);
if (dataLen > 0)
{
duk_push_lstring(ctx, data, dataLen);
free(data);
return 1;
//if (duk_peval_string(ctx, data) == 0)
//{
// duk_put_prop_string(ctx, 3, "exports");
// return 0;
//}
//else
//{
// snprintf(fileName, sizeof(fileName), "Module: %s (ERROR)", id);
// duk_push_string(ctx, fileName);
// duk_throw(ctx);
// return DUK_RET_ERROR;
//}
}
else
{
sprintf_s(fileName, sizeof(fileName), "Module: %s (NOT FOUND)", id);
duk_push_string(ctx, fileName);
duk_throw(ctx);
return DUK_RET_ERROR;
}
}
duk_ret_t mod_Search(duk_context *ctx)
{
duk_size_t idLen;
char *id;
ILibHashtable *table;
ILibDuktape_ModSearch_PUSH_Object func = NULL;
void *chain;
ILibSimpleDataStore mDS = NULL;
char *module;
if (!duk_is_string(ctx, 0)) { return ILibDuktape_Error(ctx, "mod_search(): Invalid 'ID' parameter"); }
id = (char*)duk_get_lstring(ctx, 0, &idLen);
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "chain"); // [func][chain]
chain = duk_to_pointer(ctx, -1);
duk_get_prop_string(ctx, -2, "SimpleDS"); // [func][chain][DB]
mDS = (ILibSimpleDataStore)duk_to_pointer(ctx, -1);
duk_push_heap_stash(ctx);
duk_get_prop_string(ctx, -1, "ModSearchTable");
table = (ILibHashtable)duk_to_pointer(ctx, -1);
func = (ILibDuktape_ModSearch_PUSH_Object)ILibHashtable_Get(table, NULL, id, (int)idLen);
if (func == NULL)
{
if ((module = (char*)ILibHashtable_Get(table, ILibDuktape_ModSearch_ModuleFile, id, (int)idLen)) != NULL)
{
duk_push_string(ctx, module);
return(1);
}
else if (mDS == NULL)
{
return mod_Search_Files(ctx, id);
}
else
{
char key[255];
int keyLen;
char *value;
int valueLen;
keyLen = sprintf_s(key, sizeof(key), "__MODULE:%s", id);
valueLen = ILibSimpleDataStore_GetEx(mDS, key, keyLen, NULL, 0);
if (valueLen > 0)
{
value = ILibMemory_Allocate(valueLen, 0, NULL, NULL);
ILibSimpleDataStore_GetEx(mDS, key, keyLen, value, valueLen);
duk_push_lstring(ctx, value, valueLen);
return 1;
}
else
{
sprintf_s(key, sizeof(key), "Module: %s (NOT FOUND in DB)", id);
duk_push_string(ctx, key);
duk_throw(ctx);
return DUK_RET_ERROR;
}
}
}
else
{
func(ctx, chain);
duk_put_prop_string(ctx, 3, "exports");
return 0;
}
}
void ILibDuktape_ModSearch_Destroy(duk_context *ctx, void *user)
{
duk_push_heap_stash(ctx); // [stash]
if (duk_has_prop_string(ctx, -1, "ModSearchTable"))
{
duk_get_prop_string(ctx, -1, "ModSearchTable"); // [stash][ptr]
ILibHashtable_Destroy((ILibHashtable)duk_to_pointer(ctx, -1));
duk_del_prop_string(ctx, -2, "ModSearchTable");
duk_pop_2(ctx);
}
else
{
duk_pop(ctx);
}
}
void ILibDuktape_ModSearch_Init(duk_context * ctx, void * chain, ILibSimpleDataStore mDB)
{
duk_push_heap_stash(ctx); // [stash]
duk_push_pointer(ctx, chain); // [stash][chain]
duk_put_prop_string(ctx, -2, ILibDuktape_Context_Chain); // [stash]
duk_pop(ctx); // ...
duk_get_global_string(ctx, "Duktape"); // [globalString]
duk_push_c_function(ctx, mod_Search, 4); // [globalString][func]
duk_push_pointer(ctx, chain); // [globalString][func][chain]
duk_put_prop_string(ctx, -2, "chain"); // [globalString][func]
if (mDB != NULL)
{
duk_push_pointer(ctx, mDB); // [globalString][func][DB]
duk_put_prop_string(ctx, -2, "SimpleDS"); // [globalString][func]
}
duk_put_prop_string(ctx, -2, "modSearch"); // [globalString]
duk_pop(ctx); // ...
ILibDuktape_Helper_AddHeapFinalizer(ctx, ILibDuktape_ModSearch_Destroy, NULL);
}

View File

@@ -0,0 +1,29 @@
/*
Copyright 2006 - 2017 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 ___ILIBDUKTAPEMODSEARCH___
#define ___ILIBDUKTAPEMODSEARCH___
#include "duktape.h"
#include "microstack/ILibSimpleDataStore.h"
typedef void (*ILibDuktape_ModSearch_PUSH_Object)(duk_context *ctx, void *chain);
int ILibDuktape_ModSearch_AddHandler(duk_context *ctx, char *id, ILibDuktape_ModSearch_PUSH_Object handler);
int ILibDuktape_ModSearch_AddModule(duk_context *ctx, char *id, char *module, int moduleLen);
void ILibDuktape_ModSearch_Init(duk_context *ctx, void *chain, ILibSimpleDataStore mDB);
#endif

View File

@@ -0,0 +1,90 @@
/*
Copyright 2006 - 2017 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>
#endif
#include "microstack/ILibParsers.h"
#include "microstack/ILibAsyncServerSocket.h"
#include "ILibDuktape_Helpers.h"
#include "duktape.h"
typedef struct ILibDuktape_Debugger
{
duk_context *ctx;
#ifdef WIN32
SOCKET listener;
SOCKET client;
#else
int listener;
int client;
#endif
}ILibDuktape_Debugger;
duk_size_t ILibDuktape_Debugger_ReadCB(void *udata, char *buffer, duk_size_t length)
{
ILibDuktape_Debugger *dbg = (ILibDuktape_Debugger*)udata;
return (duk_size_t)recv(dbg->client, buffer, (int)length, 0);
}
duk_size_t ILibDuktape_Debugger_WriteCB(void *udata, const char *buffer, duk_size_t length)
{
ILibDuktape_Debugger *dbg = (ILibDuktape_Debugger*)udata;
return (duk_size_t)send(dbg->client, buffer, (int)length, 0);
}
void ILibDuktape_Debugger_DetachCB(void *udata)
{
}
void ILibDuktape_Debugger_Start(duk_context *ctx, unsigned short debugPort)
{
ILibDuktape_Debugger *dbg;
struct sockaddr_in6 local_int;
struct sockaddr_in6 remote_int;
int remote_int_size = sizeof(struct sockaddr_in6);
memset(&local_int, 0, sizeof(struct sockaddr_in6));
local_int.sin6_family = AF_INET;
((struct sockaddr_in*)&local_int)->sin_addr.s_addr = INADDR_ANY;
local_int.sin6_port = htons(debugPort);
duk_push_global_object(ctx); // [obj]
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_Debugger)); // [obj][buf]
dbg = (ILibDuktape_Debugger*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, "_DbgObj"); // [obj]
duk_pop(ctx); // ...
memset(dbg, 0, sizeof(ILibDuktape_Debugger));
dbg->ctx = ctx;
if((dbg->listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { dbg->listener = (SOCKET)~0; return; }
bind(dbg->listener, (struct sockaddr*)&local_int, sizeof(struct sockaddr_in6));
listen(dbg->listener, 1);
dbg->client = accept(dbg->listener, (struct sockaddr*)&remote_int, &remote_int_size);
duk_debugger_attach(ctx, ILibDuktape_Debugger_ReadCB, ILibDuktape_Debugger_WriteCB, NULL, NULL, NULL, ILibDuktape_Debugger_DetachCB, (void*)dbg);
}
void ILibDuktape_Debugger_Stop(duk_context *ctx)
{
}

View File

@@ -0,0 +1,26 @@
/*
Copyright 2006 - 2017 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_DEBUGGER__
#define __DUKTAPE_DEBUGGER__
#include "duktape.h"
void ILibDuktape_Debugger_Start(duk_context *ctx, unsigned short debugPort);
#endif

View File

@@ -0,0 +1,562 @@
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(_MINCORE)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif
#ifdef WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <Windows.h>
#include <WinBase.h>
#else
#include <sys/types.h>
#include <ifaddrs.h>
#endif
#include "ILibDuktape_Dgram.h"
#include "ILibDuktape_Helpers.h"
#include "ILibDuktapeModSearch.h"
#include "ILibDuktape_EventEmitter.h"
#include "microstack/ILibParsers.h"
#include "microstack/ILibAsyncUDPSocket.h"
#include "microstack/ILibAsyncSocket.h"
#include "microstack/ILibRemoteLogging.h"
#define ILibDuktape_DGRAM_CHAIN "\xFF_DGRAM_CHAIN"
#define ILibDuktape_DGRAM_SOCKET_NATIVE "\xFF_DGRAM_SOCKET_NATIVE"
#define ILibDuktape_DGRAM_MULTICAST_MEMBERSHIP_TYPE "\xFF_addRemove"
typedef struct ILibDuktape_DGRAM_DATA
{
duk_context *ctx;
ILibDuktape_EventEmitter *emitter;
void *socketObject;
void *dgramObject;
void *chain;
void *OnClose, *OnError, *OnListening, *OnMessage, *OnSendOK;
ILibAsyncUDPSocket_SocketModule *mSocket;
}ILibDuktape_DGRAM_DATA;
typedef enum ILibDuktape_DGRAM_Config
{
ILibDuktape_DGRAM_Config_NONE = 0x00,
ILibDuktape_DGRAM_Config_IPv4 = 0x01,
ILibDuktape_DGRAM_Config_IPv6 = 0x02,
ILibDuktape_DGRAM_Config_ReuseAddr = 0x04
}ILibDuktape_DGRAM_Config;
ILibDuktape_DGRAM_DATA* ILibDuktape_DGram_GetPTR(duk_context *ctx)
{
ILibDuktape_DGRAM_DATA *ptrs;
duk_push_this(ctx); // [socket]
duk_get_prop_string(ctx, -1, ILibDuktape_DGRAM_SOCKET_NATIVE); // [socket][ptrs]
ptrs = (ILibDuktape_DGRAM_DATA*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop_2(ctx); // ...
return ptrs;
}
duk_ret_t ILibDuktape_Dgram_Finalizer(duk_context *ctx)
{
return 0;
}
void ILibDuktape_Dgram_Socket_OnData(ILibAsyncUDPSocket_SocketModule socketModule, char* buffer, int bufferLength, struct sockaddr_in6 *remoteInterface, void *user, void *user2, int *PAUSE)
{
ILibDuktape_DGRAM_DATA* ptrs = (ILibDuktape_DGRAM_DATA*)user;
if (ptrs != NULL && ptrs->ctx != NULL && ptrs->OnMessage != NULL)
{
duk_push_heapptr(ptrs->ctx, ptrs->OnMessage); // [func]
duk_push_heapptr(ptrs->ctx, ptrs->socketObject); // [func][this]
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_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"); }
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)
{
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"); }
}
}
#ifndef WIN32
int ILibDuktape_DGram_getIPv6ScopeID(struct in6_addr *addr)
{
int retVal = 0;
struct ifaddrs *addrlist;
struct ifaddrs *current;
if (getifaddrs(&addrlist) == 0)
{
current = addrlist;
while (current != NULL)
{
if (current->ifa_addr != NULL)
{
if (((struct sockaddr_in6*)current->ifa_addr)->sin6_family == AF_INET6 && memcmp(&(((struct sockaddr_in6*)current->ifa_addr)->sin6_addr), addr, 16)==0)
{
retVal = if_nametoindex(current->ifa_name);
break;
}
}
current = current->ifa_next;
}
freeifaddrs(addrlist);
}
return(retVal);
}
#endif
duk_ret_t ILibDuktape_DGram_Socket_bind(duk_context *ctx)
{
int i;
int config;
int nargs = duk_get_top(ctx);
ILibDuktape_DGRAM_DATA *ptrs = ILibDuktape_DGram_GetPTR(ctx);
struct sockaddr_in6 local;
void *bindCallback = NULL;
unsigned short port = 0;
duk_push_current_function(ctx); // [socket][func]
config = Duktape_GetIntPropertyValue(ctx, -1, "config", 0);
char *address = ((config & ILibDuktape_DGRAM_Config_IPv6) == ILibDuktape_DGRAM_Config_IPv6) ? "::1" : "127.0.0.1";
// [socket]
if (duk_is_object(ctx, 0))
{
// 'options'
port = (unsigned short)Duktape_GetIntPropertyValue(ctx, 0, "port", 0);
address = Duktape_GetStringPropertyValue(ctx, 0, "address", address);
if (duk_has_prop_string(ctx, 0, "exclusive"))
{
if (Duktape_GetBooleanProperty(ctx, 0, "exclusive", 0) == 0)
{
// SHARED
if (!((config & ILibDuktape_DGRAM_Config_ReuseAddr) == ILibDuktape_DGRAM_Config_ReuseAddr))
{
// Set flag
config |= ILibDuktape_DGRAM_Config_ReuseAddr;
}
}
else
{
// EXCLUSIVE
if ((config & ILibDuktape_DGRAM_Config_ReuseAddr) == ILibDuktape_DGRAM_Config_ReuseAddr)
{
// Clear flag
config ^= ILibDuktape_DGRAM_Config_ReuseAddr;
}
}
}
if (nargs > 1) { bindCallback = duk_require_heapptr(ctx, 1); }
}
else
{
for (i = 0; i < nargs; ++i)
{
if (duk_is_number(ctx, i)) { port = (unsigned short)duk_require_int(ctx, i); }
if (duk_is_string(ctx, i)) { address = (char*)duk_require_string(ctx, i); }
if (duk_is_function(ctx, i)) { bindCallback = duk_require_heapptr(ctx, i); }
}
}
if (ILibResolveEx(address, port, &local) != 0 || local.sin6_family == AF_UNSPEC) { return ILibDuktape_Error(ctx, "dgram.socket.bind(): Unable to resolve host: %s", address); }
#ifndef WIN32
if (local.sin6_family == AF_INET6 && !IN6_IS_ADDR_UNSPECIFIED(&(local.sin6_addr)))
{
local.sin6_scope_id = ILibDuktape_DGram_getIPv6ScopeID(&(local.sin6_addr));
}
#endif
if (bindCallback != NULL) ILibDuktape_EventEmitter_AddOnce(ptrs->emitter, "listening", bindCallback);
ptrs->mSocket = ILibAsyncUDPSocket_CreateEx(ptrs->chain,
4096, (struct sockaddr*)&local,
((config & ILibDuktape_DGRAM_Config_ReuseAddr) == ILibDuktape_DGRAM_Config_ReuseAddr) ? ILibAsyncUDPSocket_Reuse_SHARED : ILibAsyncUDPSocket_Reuse_EXCLUSIVE,
ILibDuktape_Dgram_Socket_OnData, ILibDuktape_Dgram_Socket_OnSendOK, ptrs);
if (ptrs->mSocket == NULL)
{
#ifdef WIN32
return(ILibDuktape_Error(ctx, "dgram.bind(): Cannot bind to (%s) Error (%d)", ILibRemoteLogging_ConvertAddress((struct sockaddr*)&local), WSAGetLastError()));
#else
return(ILibDuktape_Error(ctx, "dgram.bind(): Cannot bind to (%s) Error (%d)", ILibRemoteLogging_ConvertAddress((struct sockaddr*)&local), errno));
#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); // ...
}
return 0;
}
duk_ret_t ILibDuktape_DGram_multicastMembership(duk_context *ctx)
{
ILibDuktape_DGRAM_DATA *ptrs = ILibDuktape_DGram_GetPTR(ctx);
char *address = (char*)duk_require_string(ctx, 0);
struct sockaddr_in6 multicastAddr;
struct sockaddr_in6 localAddr;
duk_push_current_function(ctx);
duk_get_prop_string(ctx, -1, ILibDuktape_DGRAM_MULTICAST_MEMBERSHIP_TYPE);
int isAdd = strcmp((char*)duk_get_string(ctx, -1), "add") == 0 ? 1 : 0;
memset(&multicastAddr, 0, sizeof(struct sockaddr_in6));
memset(&localAddr, 0, sizeof(struct sockaddr_in6));
ILibResolveEx(address, 0, &multicastAddr);
if (isAdd != 0)
{
switch (multicastAddr.sin6_family)
{
case AF_INET:
ILibAsyncUDPSocket_JoinMulticastGroupV4(ptrs->mSocket, (struct sockaddr_in*)&multicastAddr, (struct sockaddr*)&localAddr);
break;
case AF_INET6:
ILibAsyncUDPSocket_JoinMulticastGroupV6(ptrs->mSocket, &multicastAddr, 0);
break;
default:
return ILibDuktape_Error(ctx, "dgram.addMembership(): Invalid Multicast Address '%s'", address);
break;
}
}
else
{
switch (multicastAddr.sin6_family)
{
case AF_INET:
ILibAsyncUDPSocket_DropMulticastGroupV4(ptrs->mSocket, (struct sockaddr_in*)&multicastAddr, (struct sockaddr*)&localAddr);
break;
case AF_INET6:
ILibAsyncUDPSocket_DropMulticastGroupV6(ptrs->mSocket, &multicastAddr, 0);
break;
default:
return ILibDuktape_Error(ctx, "dgram.dropMembership(): Invalid Multicast Address '%s'", address);
break;
}
}
return 0;
}
duk_ret_t ILibDuktape_DGram_setMulticastTTL(duk_context *ctx)
{
ILibDuktape_DGRAM_DATA *ptrs = ILibDuktape_DGram_GetPTR(ctx);
ILibAsyncUDPSocket_SetMulticastTTL(ptrs->mSocket, duk_require_int(ctx, 0));
return 0;
}
duk_ret_t ILibDuktape_DGram_setMulticastLoopback(duk_context *ctx)
{
ILibDuktape_DGRAM_DATA *ptrs = ILibDuktape_DGram_GetPTR(ctx);
ILibAsyncUDPSocket_SetMulticastLoopback(ptrs->mSocket, duk_require_boolean(ctx, 0) ? 1 : 0);
return 0;
}
duk_ret_t ILibDuktape_DGram_send(duk_context *ctx)
{
/*
msg <Buffer> | <Uint8Array> | <string> | <array> Message to be sent
offset <number> Integer.Optional.Offset in the buffer where the message starts.
length <number> Integer.Optional.Number of bytes in the message.
port <number> Integer.Destination port.
address <string> Destination hostname or IP address.Optional.
callback <Function> Called when the message has been sent.Optional.*/
int nargs = duk_get_top(ctx);
ILibDuktape_DGRAM_DATA *ptrs = ILibDuktape_DGram_GetPTR(ctx);
duk_size_t bufferLen;
char *buffer = Duktape_GetBuffer(ctx, 0, &bufferLen);
int offset = 0;
unsigned short port = 0;
int i;
struct sockaddr_in6 local;
local.sin6_family = AF_UNSPEC;
void *onSendOk = NULL;
if (nargs >= 4 && duk_is_number(ctx, 1) && duk_is_number(ctx, 2))
{
offset = duk_require_int(ctx, 1);
bufferLen = (duk_size_t)duk_require_int(ctx, 2);
port = (unsigned short)duk_require_int(ctx, 3);
for (i = 4; i < nargs; ++i)
{
if (duk_is_string(ctx, i)) { ILibResolveEx((char*)duk_require_string(ctx, i), port, &local); }
if (duk_is_function(ctx, i)) { onSendOk = duk_require_heapptr(ctx, i); }
}
}
else
{
port = (unsigned short)duk_require_int(ctx, 1);
for (i = 2; i < nargs; ++i)
{
if (duk_is_string(ctx, i)) { ILibResolveEx((char*)duk_require_string(ctx, i), port, &local); }
if (duk_is_function(ctx, i)) { onSendOk = duk_require_heapptr(ctx, i); }
}
}
if (local.sin6_family == AF_UNSPEC)
{
ILibAsyncUDPSocket_GetLocalInterface(ptrs->mSocket, (struct sockaddr*)&local);
if (local.sin6_family == AF_INET6)
{
ILibResolveEx("::1", port, &local);
}
else
{
ILibResolveEx("127.0.0.1", port, &local);
}
}
switch (ILibAsyncUDPSocket_SendTo(ptrs->mSocket, (struct sockaddr*)&local, buffer + offset, (int)bufferLen, ILibAsyncSocket_MemoryOwnership_USER))
{
case ILibAsyncSocket_ALL_DATA_SENT:
if (onSendOk != NULL)
{
duk_push_heapptr(ctx, onSendOk); // [func]
duk_push_heapptr(ctx, ptrs->socketObject); // [func][this]
if (duk_pcall_method(ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "net.dgram.send.callback(): Error "); }
duk_pop(ctx); // ...
}
break;
case ILibAsyncSocket_NOT_ALL_DATA_SENT_YET:
if (onSendOk != NULL) { ILibDuktape_EventEmitter_AddOnce(ptrs->emitter, "flushed", onSendOk); }
break;
default:
// Error Occured
if (onSendOk != NULL)
{
duk_push_heapptr(ctx, onSendOk); // [func]
duk_push_heapptr(ctx, ptrs->socketObject); // [func][this]
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.send.callback(): Error "); }
duk_pop(ctx); // ...
}
else if(ptrs->OnError != NULL)
{
duk_push_heapptr(ctx, ptrs->OnError); // [func]
duk_push_heapptr(ctx, ptrs->socketObject); // [func][this]
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 "); }
duk_pop(ctx); // ...
}
break;
}
return 0;
}
duk_ret_t ILibDuktape_DGram_setBroadcast(duk_context *ctx)
{
ILibDuktape_DGRAM_DATA *ptrs = ILibDuktape_DGram_GetPTR(ctx);
int enable = (int)duk_require_boolean(ctx, 0);
ILibAsyncUDPSocket_SetBroadcast(ptrs->mSocket, enable);
return(0);
}
duk_ret_t ILibDuktape_DGram_setTTL(duk_context *ctx)
{
return ILibDuktape_Error(ctx, "Not implemented");
}
duk_ret_t ILibDuktape_DGram_createSocket(duk_context *ctx)
{
ILibDuktape_DGRAM_Config config = ILibDuktape_DGRAM_Config_NONE;
ILibDuktape_DGRAM_DATA *ptrs;
void *chain;
char *typ = duk_is_string(ctx, 0) ? (char*)duk_require_string : Duktape_GetStringPropertyValue(ctx, 0, "type", "udp4");
void *dgram;
duk_push_this(ctx); // [dgram]
dgram = duk_get_heapptr(ctx, -1);
duk_get_prop_string(ctx, -1, ILibDuktape_DGRAM_CHAIN); // [dgram][chain]
chain = duk_get_pointer(ctx, -1);
if (strncmp(typ, "udp4", 4) == 0) { config |= ILibDuktape_DGRAM_Config_IPv4; }
else if (strncmp(typ, "udp6", 4) == 0) { config |= ILibDuktape_DGRAM_Config_IPv6; }
else { return ILibDuktape_Error(ctx, "dgram.createSocket(): Invalid 'type' specified: %s", typ); }
if (!duk_is_string(ctx, 0)) { if (Duktape_GetBooleanProperty(ctx, 0, "reuseAddr", 0) != 0) { config |= ILibDuktape_DGRAM_Config_ReuseAddr; } }
/**************************************************************************************/
duk_push_object(ctx); // [socket]
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_Dgram_Finalizer);
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_DGRAM_DATA)); // [socket][native]
ptrs = (ILibDuktape_DGRAM_DATA*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, ILibDuktape_DGRAM_SOCKET_NATIVE); // [socket]
memset(ptrs, 0, sizeof(ILibDuktape_DGRAM_DATA));
ptrs->ctx = ctx;
ptrs->chain = chain;
ptrs->socketObject = duk_get_heapptr(ctx, -1);
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_CreateInstanceMethodWithIntProperty(ctx, "config", config, "bind", ILibDuktape_DGram_Socket_bind, DUK_VARARGS);
ILibDuktape_CreateInstanceMethodWithStringProperty(ctx, ILibDuktape_DGRAM_MULTICAST_MEMBERSHIP_TYPE, "add", "addMembership", ILibDuktape_DGram_multicastMembership, DUK_VARARGS);
ILibDuktape_CreateInstanceMethodWithStringProperty(ctx, ILibDuktape_DGRAM_MULTICAST_MEMBERSHIP_TYPE, "remove", "dropMembership", ILibDuktape_DGram_multicastMembership, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "send", ILibDuktape_DGram_send, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "setBroadcast", ILibDuktape_DGram_setBroadcast, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "setMulticastLoopback", ILibDuktape_DGram_setMulticastLoopback, 1);
ILibDuktape_CreateInstanceMethod(ctx, "setMulticastTTL", ILibDuktape_DGram_setMulticastTTL, 1);
ILibDuktape_CreateInstanceMethod(ctx, "setTTL", ILibDuktape_DGram_setTTL, 1);
return 1;
}
void ILibDuktape_DGram_PUSH(duk_context *ctx, void *chain)
{
duk_push_object(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);
}
void ILibDuktape_DGram_Init(duk_context *ctx)
{
ILibDuktape_ModSearch_AddHandler(ctx, "dgram", ILibDuktape_DGram_PUSH);
}
#ifdef __DOXY__
/*!
\brief UDP Datagram Implementation
*/
class dgram
{
public:
/*!
\brief Create's a Socket object.
*
Once the socket is created, calling bind() will instruct the Socket to begin listening for datagram messages.\n
When address and port are not passed to bind() the method will bind the Socket to the "all interfaces" address on a random port\n
The bound address and port can be retrieved using address().address and address().port.
\param options <Object>\n
<b>type</b> \<String\> Required. The family of socket. Must be either 'udp4' or 'udp6'.\n
<b>reuseAddr</b> <boolean> Optional If specified, will set the reuseAddr flag appropriately.
\return New Socket instance.
*/
static Socket createSocket(options[, callback]);
/*!
\implements EventEmitter
\brief dgram.Socket is an EventEmitter that encapsulates datagram functionality.
*/
class Socket
{
public:
/*!
\brief Event is emitted after a Socket is closed with close(). Once triggered, no new 'message' events will be emitted on this Socket.
*/
void close;
/*!
\brief Event is emitted whenever any error occurs. The event handler function is passed a single Error object.
\param err <Error>
*/
void error;
/*!
\brief Event is emitted whenever a Socket begins listening for datagram messages. This occurs as soon as UDP sockets are created.
*/
void listening;
/*!
\brief Event is emitted when a new datagram is available on a Socket.
\param msg <Buffer> The message
\param rinfo <Object> Remote Address Information\n
<b>address</b> \<String\> Sender Address\n
<b>family</b> \<String\> Address Family ('IPv4' or 'IPv6')\n
<b>port</b> <Number> Sender Port\n
<b>size</b> <Number> Message Size\n
*/
void message;
/*!
\brief Event emitted when send buffer is empty
*/
void flushed;
/*!
\brief Causes the Socket to listen for datagram messages on a named port and optional address
\param options <Object> Required. Supports the following properties:\n
<b>port</b> <Number> Optional\n
<b>address</b> \<String\> Optional\n
<b>exclusive</b> <boolean> Optional\n
\param callback <func> Optional callback that will be set as one time listener to 'listening' event.
*/
void bind(options[, callback]);
/*!
\brief Join a multicast group at the given multicastAddress and multicastInterface using the IP_ADD_MEMBERSHIP socket option
\param multicastAddress \<String\>
\param multicastInterface \<String\> Optional
*/
void addMembership(multicastAddress[, multicastInterface]);
/*!
\brief Leave a multicast group at multicastAddress using the IP_DROP_MEMBERSHIP socket option.
\param multicastAddress \<String\>
\param multicastInterface \<String\> Optional
*/
void dropMembership(multicastAddress[, multicastInterface]);
/*!
\brief Send a datagram on the socket. The destination port and address must be specified.
\param msg \<Buffer\|String\> Message to be sent
\param offset <Integer> Optional. Offset in the buffer where the message starts
\param length <Integer> Optional. Number of bytes in the message
\param port <Integer> Destination port
\param address \<String\> Optional. Destination hostname or IP Address.
\param callback <func> Optional. Set as one time listener for 'flush' event.
*/
void send(msg, [offset, length, ] port[, address][, callback]);
/*!
\brief Sets or clears the SO_BROADCAST socket option.
\param flag <boolean> When set to true, UDP packets may be sent to a local interface's broadcast address
*/
void setBroadcast(flag);
/*!
\brief Sets or clears the IP_MULTICAST_LOOP socket option.
\param flag <boolean> When set to true, multicast packets will also be received on the local interface.
*/
void setMulticastLoopback(flag);
/*!
\brief Sets the default outgoing multicast interface of the socket to a chosen interface or back to system interface selection.
\param multicastInterface \<String\> Must be a valid string representation of an IP from the socket's family.
*/
void setMulticastInterface(multicastInterface);
/*!
\brief Sets the IP_MULTICAST_TTL socket option
\param ttl <Integer>
*/
void setMulticastTTL(ttl);
/*!
\brief Sets the IP_TTL socket option
\param ttl <Integer>
*/
void setTTL(ttl)
};
};
#endif

View File

@@ -0,0 +1,9 @@
#ifndef ___ILibDuktape_Dgram___
#define ___ILibDuktape_Dgram___
#include "duktape.h"
void ILibDuktape_DGram_Init(duk_context *ctx);
#endif

View File

@@ -0,0 +1,74 @@
/*
Copyright 2006 - 2017 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 "ILibDuktape_DuplexStream.h"
#ifdef __DOXY__
/*!
\implements ReadableStream
\implements WritableStream
\brief DuplexStreams are streams that implement both the Readable and Writable interfaces.
*/
public class DuplexStream
{
private DuplexStream();
};
#endif
void ILibDuktape_DuplexStream_OnPause(struct ILibDuktape_readableStream *sender, void *user)
{
ILibDuktape_DuplexStream *ds = (ILibDuktape_DuplexStream*)user;
if (ds->OnPause != NULL) { ((ILibDuktape_DuplexStream_PauseResumeHandler)ds->OnPause)(ds, ds->user); }
}
void ILibDuktape_DuplexStream_OnResume(struct ILibDuktape_readableStream *sender, void *user)
{
ILibDuktape_DuplexStream *ds = (ILibDuktape_DuplexStream*)user;
if (ds->OnResume != NULL) { ((ILibDuktape_DuplexStream_PauseResumeHandler)ds->OnResume)(ds, ds->user); }
}
ILibTransport_DoneState ILibDuktape_DuplexStream_OnWrite(struct ILibDuktape_WritableStream *stream, char *buffer, int bufferLen, void *user)
{
ILibDuktape_DuplexStream *ds = (ILibDuktape_DuplexStream*)user;
if (ds->OnWrite != NULL) { return ((ILibDuktape_DuplexStream_WriteHandler)ds->OnWrite)(ds, buffer, bufferLen, ds->user); }
return ILibTransport_DoneState_ERROR;
}
void ILibDuktape_DuplexStream_OnEnd(struct ILibDuktape_WritableStream *stream, void *user)
{
ILibDuktape_DuplexStream *ds = (ILibDuktape_DuplexStream*)user;
if (ds->OnEnd != NULL) { ((ILibDuktape_DuplexStream_EndHandler)ds->OnEnd)(ds, ds->user); }
}
ILibDuktape_DuplexStream * ILibDuktape_DuplexStream_Init(duk_context * ctx, ILibDuktape_DuplexStream_WriteHandler WriteHandler, ILibDuktape_DuplexStream_EndHandler EndHandler, ILibDuktape_DuplexStream_PauseResumeHandler PauseHandler, ILibDuktape_DuplexStream_PauseResumeHandler ResumeHandler, void * user)
{
ILibDuktape_DuplexStream *retVal;
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_DuplexStream)); // [obj][buffer]
retVal = (ILibDuktape_DuplexStream*)Duktape_GetBuffer(ctx, -1, NULL); // [obj][buffer]
duk_put_prop_string(ctx, -2, ILibDuktape_DuplexStream_bufferPtr); // [obj]
memset(retVal, 0, sizeof(ILibDuktape_DuplexStream));
retVal->user = user;
retVal->readableStream = ILibDuktape_InitReadableStream(ctx, ILibDuktape_DuplexStream_OnPause, ILibDuktape_DuplexStream_OnResume, retVal);
retVal->writableStream = ILibDuktape_WritableStream_Init(ctx, ILibDuktape_DuplexStream_OnWrite, ILibDuktape_DuplexStream_OnEnd, retVal);
retVal->OnEnd = EndHandler;
retVal->OnWrite = WriteHandler;
retVal->OnPause = PauseHandler;
retVal->OnResume = ResumeHandler;
retVal->ParentObject = duk_get_heapptr(ctx, -1);
return retVal;
}

View File

@@ -0,0 +1,51 @@
/*
Copyright 2006 - 2017 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_DUPLEXSTREAM___
#define ___ILIBDUKTAPE_DUPLEXSTREAM___
#include "duktape.h"
#include "microstack/ILibParsers.h"
#include "ILibDuktape_ReadableStream.h"
#include "ILibDuktape_WritableStream.h"
#define ILibDuktape_DuplexStream_bufferPtr "\xFF_DuplexStreamPtr"
typedef struct ILibDuktape_DuplexStream
{
ILibDuktape_readableStream *readableStream;
ILibDuktape_WritableStream *writableStream;
void *user;
void *ParentObject;
void *OnWrite;
void *OnEnd;
void *OnPause;
void *OnResume;
}ILibDuktape_DuplexStream;
typedef ILibTransport_DoneState(*ILibDuktape_DuplexStream_WriteHandler)(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user);
typedef void(*ILibDuktape_DuplexStream_EndHandler)(ILibDuktape_DuplexStream *stream, void *user);
typedef void(*ILibDuktape_DuplexStream_PauseResumeHandler)(ILibDuktape_DuplexStream *sender, void *user);
#define ILibDuktape_DuplexStream_Ready(duplexStream) ILibDuktape_WritableStream_Ready((duplexStream)->writableStream)
#define ILibDuktape_DuplexStream_WriteData(duplexStream, buffer, bufferLen) ILibDuktape_readableStream_WriteData((duplexStream)->readableStream, buffer, bufferLen)
#define ILibDuktape_DuplexStream_WriteEnd(duplexStream) ILibDuktape_readableStream_WriteEnd((duplexStream)->readableStream)
#define ILibDuktape_DuplexStream_Closed(duplexStream) ILibDuktape_readableStream_Closed((duplexStream)->readableStream)
ILibDuktape_DuplexStream* ILibDuktape_DuplexStream_Init(duk_context *ctx, ILibDuktape_DuplexStream_WriteHandler WriteHandler, ILibDuktape_DuplexStream_EndHandler EndHandler, ILibDuktape_DuplexStream_PauseResumeHandler PauseHandler, ILibDuktape_DuplexStream_PauseResumeHandler ResumeHandler, void *user);
#endif

View File

@@ -0,0 +1,253 @@
#include "duktape.h"
#include "ILibDuktape_Helpers.h"
#include "ILibParsers_Duktape.h"
#include "ILibDuktapeModSearch.h"
#include "ILibDuktape_DuplexStream.h"
#include "ILibDuktape_ReadableStream.h"
#include "ILibDuktape_WritableStream.h"
#include "microstack/ILibCrypto.h"
#ifndef MICROSTACK_NOTLS
#include <openssl/aes.h>
#include <openssl/crypto.h>
typedef struct ILibDuktape_EncryptionStream_Ptrs
{
duk_context *ctx;
void *object;
ILibDuktape_DuplexStream *encrypted;
ILibDuktape_DuplexStream *clear;
EVP_CIPHER_CTX *encryptedCTX;
EVP_CIPHER_CTX *decryptedCTX;
}ILibDuktape_EncryptionStream_Ptrs;
#define ILibDuktape_EncryptionStream_Buffer "\xFF_EncryptionStream_Buffer"
#define ILibDuktape_EncryptionStream_clearStream "\xFF_EncryptionStream_clearStream"
#define ILibDuktape_EncryptionStream_encryptedStream "\xFF_EncryptionStream_encryptedStream"
ILibTransport_DoneState ILibDuktape_EncryptionStream_encrypted_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user)
{
ILibDuktape_EncryptionStream_Ptrs *ptrs = (ILibDuktape_EncryptionStream_Ptrs*)user;
char out[5000];
int outLen;
int i = 0;
int result = 0;
while (i < bufferLen)
{
EVP_DecryptUpdate(ptrs->decryptedCTX, (unsigned char*)out, &outLen, (unsigned char*)(buffer + i), bufferLen - i > 4096 ? 4096 : bufferLen - i);
result = ILibDuktape_DuplexStream_WriteData(ptrs->clear, out, outLen);
i += 4096;
}
return (result == 0 ? ILibTransport_DoneState_COMPLETE : ILibTransport_DoneState_INCOMPLETE);
}
ILibTransport_DoneState ILibDuktape_EncryptionStream_decrypted_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user)
{
ILibDuktape_EncryptionStream_Ptrs *ptrs = (ILibDuktape_EncryptionStream_Ptrs*)user;
char out[5000];
int outLen;
int i = 0;
int result = 0;
while (i < bufferLen)
{
EVP_EncryptUpdate(ptrs->encryptedCTX, (unsigned char*)out, &outLen, (unsigned char*)(buffer + i), bufferLen - i > 4096 ? 4096 : bufferLen - i);
result = ILibDuktape_DuplexStream_WriteData(ptrs->encrypted, out, outLen);
i += 4096;
}
return (result == 0 ? ILibTransport_DoneState_COMPLETE : ILibTransport_DoneState_INCOMPLETE);
}
void ILibDuktape_EncryptionStream_encrypted_WriteEndSink(ILibDuktape_DuplexStream *stream, void *user)
{
ILibDuktape_EncryptionStream_Ptrs *ptrs = (ILibDuktape_EncryptionStream_Ptrs*)user;
char out[5000];
int outLen = 0;
EVP_DecryptFinal(ptrs->decryptedCTX, (unsigned char*)out, &outLen);
if (outLen > 0)
{
ILibDuktape_DuplexStream_WriteData(ptrs->clear, out, outLen);
}
ILibDuktape_DuplexStream_WriteEnd(ptrs->clear);
}
void ILibDuktape_EncryptionStream_decrypted_WriteEndSink(ILibDuktape_DuplexStream *stream, void *user)
{
ILibDuktape_EncryptionStream_Ptrs *ptrs = (ILibDuktape_EncryptionStream_Ptrs*)user;
char out[5000];
int outLen = 0;
EVP_EncryptFinal(ptrs->encryptedCTX, (unsigned char*)out, &outLen);
if (outLen > 0)
{
ILibDuktape_DuplexStream_WriteData(ptrs->encrypted, out, outLen);
}
ILibDuktape_DuplexStream_WriteEnd(ptrs->encrypted);
}
void ILibDuktape_EncryptionStream_encrypted_PauseSink(ILibDuktape_DuplexStream *sender, void *user)
{
}
void ILibDuktape_EncryptionStream_encrypted_ResumeSink(ILibDuktape_DuplexStream *sender, void *user)
{
ILibDuktape_EncryptionStream_Ptrs *ptrs = (ILibDuktape_EncryptionStream_Ptrs*)user;
ILibDuktape_DuplexStream_Ready(ptrs->clear);
}
void ILibDuktape_EncryptionStream_decrypted_PauseSink(ILibDuktape_DuplexStream *sender, void *user)
{
}
void ILibDuktape_EncryptionStream_decrypted_ResumeSink(ILibDuktape_DuplexStream *sender, void *user)
{
ILibDuktape_EncryptionStream_Ptrs *ptrs = (ILibDuktape_EncryptionStream_Ptrs*)user;
ILibDuktape_DuplexStream_Ready(ptrs->encrypted);
}
duk_ret_t ILibDuktape_EncryptionStream_Finalizer(duk_context *ctx)
{
ILibDuktape_EncryptionStream_Ptrs *ptrs;
duk_get_prop_string(ctx, 0, ILibDuktape_EncryptionStream_Buffer);
ptrs = (ILibDuktape_EncryptionStream_Ptrs*)Duktape_GetBuffer(ctx, -1, NULL);
EVP_CIPHER_CTX_free(ptrs->decryptedCTX);
EVP_CIPHER_CTX_free(ptrs->encryptedCTX);
return 0;
}
duk_ret_t ILibDuktape_EncryptionStream_CreateEncryption(duk_context *ctx)
{
ILibDuktape_EncryptionStream_Ptrs *ptrs;
char *key = NULL;
char *iv = NULL;
if (!duk_has_prop_string(ctx, 0, "key")) { duk_push_string(ctx, "EncryptionStream.Create(): key must be specified!"); duk_throw(ctx); return DUK_RET_ERROR; }
if (!duk_has_prop_string(ctx, 0, "iv")) { duk_push_string(ctx, "EncryptionStream.Create(): iv must be specified!"); duk_throw(ctx); return DUK_RET_ERROR; }
duk_get_prop_string(ctx, 0, "key"); // [key]
if (duk_is_string(ctx, -1))
{
// Base64 encoded key
duk_size_t tmpLen;
char *tmp = (char*)duk_get_lstring(ctx, -1, &tmpLen);
duk_push_object(ctx); // [key][stream]
duk_push_fixed_buffer(ctx, ILibBase64DecodeLength((int)tmpLen));// [key][stream][buffer]
key = (char*)Duktape_GetBuffer(ctx, -1, NULL);
ILibBase64Decode((unsigned char*)tmp, (int)tmpLen, (unsigned char**)&key);
duk_put_prop_string(ctx, -2, "\xFF_key"); // [key][stream]
duk_swap_top(ctx, -2); // [stream][key]
duk_pop(ctx); // [stream]
}
else
{
duk_push_object(ctx); // [key][stream]
duk_swap_top(ctx, -2); // [stream][key]
key = (char*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, "\xFF_key"); // [stream]
}
duk_get_prop_string(ctx, 0, "iv"); // [stream][iv]
if (duk_is_string(ctx, -1))
{
duk_size_t tmpLen;
char *tmp = (char*)duk_get_lstring(ctx, -1, &tmpLen);
duk_push_fixed_buffer(ctx, ILibBase64DecodeLength((int)tmpLen)); // [stream][iv][buffer]
duk_swap_top(ctx, -2); // [stream][buffer][iv]
iv = (char*)Duktape_GetBuffer(ctx, -2, NULL);
ILibBase64Decode((unsigned char*)tmp, (int)tmpLen, (unsigned char**)&iv);
duk_pop(ctx); // [stream][buffer]
duk_put_prop_string(ctx, -2, "\xFF_iv"); // [stream]
}
else
{
iv = (char*)Duktape_GetBuffer(ctx, -1, NULL); // [stream][iv]
duk_put_prop_string(ctx, -2, "\xFF_iv"); // [stream]
}
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_EncryptionStream_Ptrs)); // [stream][buffer]
ptrs = (ILibDuktape_EncryptionStream_Ptrs*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, ILibDuktape_EncryptionStream_Buffer); // [stream]
memset(ptrs, 0, sizeof(ILibDuktape_EncryptionStream_Ptrs));
ptrs->ctx = ctx;
ptrs->object = duk_get_heapptr(ctx, -1);
duk_push_object(ctx); // [stream][clear]
ptrs->encrypted = ILibDuktape_DuplexStream_Init(ctx,
ILibDuktape_EncryptionStream_encrypted_WriteSink,
ILibDuktape_EncryptionStream_encrypted_WriteEndSink,
ILibDuktape_EncryptionStream_encrypted_PauseSink,
ILibDuktape_EncryptionStream_encrypted_ResumeSink,
ptrs);
duk_put_prop_string(ctx, -2, ILibDuktape_EncryptionStream_clearStream); // [stream]
duk_push_object(ctx); // [stream][encrypted]
ptrs->clear = ILibDuktape_DuplexStream_Init(ctx,
ILibDuktape_EncryptionStream_decrypted_WriteSink,
ILibDuktape_EncryptionStream_decrypted_WriteEndSink,
ILibDuktape_EncryptionStream_decrypted_PauseSink,
ILibDuktape_EncryptionStream_decrypted_ResumeSink,
ptrs);
duk_put_prop_string(ctx, -2, ILibDuktape_EncryptionStream_encryptedStream); // [stream]
ILibDuktape_CreateEventWithGetterEx(ctx, "encryptedStream", ptrs->encrypted->ParentObject);
ILibDuktape_CreateEventWithGetterEx(ctx, "decryptedStream", ptrs->clear->ParentObject);
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_EncryptionStream_Finalizer);
ptrs->encryptedCTX = EVP_CIPHER_CTX_new();
ptrs->decryptedCTX = EVP_CIPHER_CTX_new();
EVP_EncryptInit(ptrs->encryptedCTX, EVP_aes_256_ctr(), (unsigned char*)key, (unsigned char*)iv);
EVP_DecryptInit(ptrs->decryptedCTX, EVP_aes_256_ctr(), (unsigned char*)key, (unsigned char*)iv);
return 1;
}
duk_ret_t ILibDuktape_EncryptionStream_generateRandom(duk_context *ctx)
{
char *buffer;
duk_size_t bufferLen;
duk_push_fixed_buffer(ctx, duk_require_int(ctx, 0));
buffer = Duktape_GetBuffer(ctx, -1, &bufferLen);
util_random((int)bufferLen, buffer);
return 1;
}
void ILibDuktape_EncryptionStream_PUSH(duk_context *ctx, void *chain)
{
duk_push_object(ctx);
ILibDuktape_CreateInstanceMethod(ctx, "Create", ILibDuktape_EncryptionStream_CreateEncryption, 1);
ILibDuktape_CreateInstanceMethod(ctx, "GenerateRandom", ILibDuktape_EncryptionStream_generateRandom, 1);
}
#endif
void ILibDuktape_EncryptionStream_init(duk_context *ctx)
{
#ifndef MICROSTACK_NOTLS
ILibDuktape_ModSearch_AddHandler(ctx, "EncryptionStream", ILibDuktape_EncryptionStream_PUSH);
#endif
}
#ifdef __DOXY__
/*!
\brief AES256 Encryption Stream <b>Note:</b> To use, must <b>require('EncryptionStream').Create()</b>
*/
class EncryptionStream
{
public:
/*!
\brief Creates an AES256 EncryptionStream instance
\param options <Object>\n
<b>key</b> \<Buffer\|String\> Encryption key, either as a base64 encoded string, or a raw buffer\n
<b>iv</b> \<Buffer\|String\> base64 encoded string, or a raw buffer\n
*/
static EncryptionStream Create(options);
/*!
\brief Returns a buffer of the specified size, and randomly populates it with random data.
\param numBytes <integer> Size of the buffer to create
*/
static Buffer GenerateRandom(numBytes);
/*!
\brief Encrypted DuplexStream. Written encrypted data is decrypted and written to decryptedStream.
*/
DuplexStream encryptedStream;
/*!
\brief Decrypted DuplexStream. Written decrypted data is encrypted and written to encryptedStream.
*/
DuplexStream decryptedStream;
};
#endif

View File

@@ -0,0 +1,8 @@
#ifndef __ILibDuktape_EncryptionStream__
#define __ILibDuktape_EncryptionStream__
#include "duktape.h"
void ILibDuktape_EncryptionStream_init(duk_context *ctx);
#endif

View File

@@ -0,0 +1,37 @@
#ifndef __ILibDuktape_EVENT_EMITTER__
#define __ILibDuktape_EVENT_EMITTER__
#include "duktape.h"
#include "microstack/ILibParsers.h"
typedef void(*ILibDuktape_EventEmitter_Handler)(duk_context *ctx, void *object, char *eventName, void *duk_eventArgs);
typedef struct ILibDuktape_EventEmitter
{
duk_context *ctx;
void *object;
void *tmpObject;
unsigned int *totalListeners;
ILibHashtable eventTable;
}ILibDuktape_EventEmitter;
typedef void(*ILibDuktape_EventEmitter_HookHandler)(ILibDuktape_EventEmitter *sender, char *eventName, void *hookedCallback);
ILibDuktape_EventEmitter* ILibDuktape_EventEmitter_Create(duk_context *ctx);
ILibDuktape_EventEmitter* ILibDuktape_EventEmitter_GetEmitter(duk_context *ctx, duk_idx_t i);
ILibDuktape_EventEmitter* ILibDuktape_EventEmitter_GetEmitter_fromThis(duk_context *ctx);
#define ILibDuktape_EventEmitter_GetEmitter_fromCurrent(ctx) ILibDuktape_EventEmitter_GetEmitter(ctx, -1)
void ILibDuktape_EventEmitter_Init(duk_context *ctx);
void ILibDuktape_EventEmitter_RemoveAll(ILibDuktape_EventEmitter *emitter); // Removes all event handlers/dispatchers
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_AddOn(ILibDuktape_EventEmitter *emitter, char *eventName, void *heapptr); // Add native event handler
void ILibDuktape_EventEmitter_AddHook(ILibDuktape_EventEmitter *emitter, char *eventName, ILibDuktape_EventEmitter_HookHandler handler);
#endif

View File

@@ -0,0 +1,873 @@
/*
Copyright 2006 - 2017 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>
#endif
#include "duktape.h"
#include "ILibDuktape_GenericMarshal.h"
#include "ILibDuktapeModSearch.h"
#include "ILibDuktape_Helpers.h"
#include "microstack/ILibParsers.h"
#include "microstack/ILibCrypto.h"
#include "microstack/ILibRemoteLogging.h"
#if defined(_WIN64) || defined(__LP64__)
typedef uint_fast64_t PTRSIZE;
#else
typedef uint_fast32_t PTRSIZE;
#endif
#ifdef WIN32
#define APICALLTYPE __stdcall
#else
#define APICALLTYPE
#include <dlfcn.h>
#endif
typedef PTRSIZE(APICALLTYPE *R0)();
typedef PTRSIZE(APICALLTYPE *R1)(PTRSIZE V1);
typedef PTRSIZE(APICALLTYPE *R2)(PTRSIZE V1, PTRSIZE V2);
typedef PTRSIZE(APICALLTYPE *R3)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3);
typedef PTRSIZE(APICALLTYPE *R4)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4);
typedef PTRSIZE(APICALLTYPE *R5)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5);
typedef PTRSIZE(APICALLTYPE *R6)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6);
typedef PTRSIZE(APICALLTYPE *R7)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7);
typedef PTRSIZE(APICALLTYPE *R8)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8);
typedef PTRSIZE(APICALLTYPE *R9)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9);
typedef PTRSIZE(APICALLTYPE *R10)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10);
typedef struct Duktape_GenericMarshal_Proxy
{
duk_context *ctx;
void *jsCallbackPtr;
void *jsProxyObject;
}Duktape_GenericMarshal_Proxy;
void ILibDuktape_GenericMarshal_Variable_PUSH(duk_context *ctx, void *ptr, int size);
duk_ret_t ILibDuktape_GenericMarshal_Variable_Val_STRING(duk_context *ctx)
{
void *ptr;
//int size;
duk_push_this(ctx); // [var]
duk_get_prop_string(ctx, -1, "_ptr"); // [var][ptr]
ptr = duk_to_pointer(ctx, -1);
//duk_get_prop_string(ctx, -2, "_size"); // [var][ptr][size]
//size = duk_to_int(ctx, -1);
duk_push_string(ctx, (char*)ptr);
return 1;
}
duk_ret_t ILibDuktape_GenericMarshal_Variable_Val_HSTRING(duk_context *ctx)
{
void *ptr;
int size;
char hexString[255];
duk_push_this(ctx); // [var]
duk_get_prop_string(ctx, -1, "_ptr"); // [var][ptr]
ptr = duk_to_pointer(ctx, -1);
duk_get_prop_string(ctx, -2, "_size"); // [var][ptr][size]
size = duk_to_int(ctx, -1);
util_tohex((char*)ptr, size < 255 ? size : 254, hexString);
duk_push_string(ctx, (char*)hexString);
return 1;
}
duk_ret_t ILibDuktape_GenericMarshal_Variable_Val_HSTRING2(duk_context *ctx)
{
void *ptr;
int size;
char hexString[255];
duk_push_this(ctx); // [var]
duk_get_prop_string(ctx, -1, "_ptr"); // [var][ptr]
ptr = duk_to_pointer(ctx, -1);
duk_get_prop_string(ctx, -2, "_size"); // [var][ptr][size]
size = duk_to_int(ctx, -1);
util_tohex2((char*)ptr, size < 255 ? size : 254, hexString);
duk_push_string(ctx, (char*)hexString);
return 1;
}
duk_ret_t ILibDuktape_GenericMarshal_Variable_Val_ASTRING(duk_context *ctx)
{
void *ptr;
int size;
#ifdef WIN32
char astr[65535];
size_t s;
#endif
duk_push_this(ctx); // [var]
duk_get_prop_string(ctx, -1, "_ptr"); // [var][ptr]
ptr = duk_to_pointer(ctx, -1);
duk_get_prop_string(ctx, -2, "_size"); // [var][ptr][size]
size = duk_to_int(ctx, -1);
#ifdef WIN32
wcstombs_s(&s, astr, sizeof(astr), (const wchar_t*)ptr, size);
duk_push_string(ctx, (char*)astr);
#else
duk_push_lstring(ctx, (const char*)ptr, size);
#endif
return 1;
}
duk_ret_t ILibDuktape_GenericMarshal_Variable_Val_GET(duk_context *ctx)
{
void *ptr;
int size;
duk_push_this(ctx); // [var]
duk_get_prop_string(ctx, -1, "_ptr"); // [var][ptr]
ptr = duk_to_pointer(ctx, -1);
duk_get_prop_string(ctx, -2, "_size"); // [var][ptr][size]
size = duk_to_int(ctx, -1);
switch (size)
{
case 2:
duk_push_int(ctx, (int)((unsigned short*)ptr)[0]);
break;
case 4:
duk_push_int(ctx, (int)((unsigned int*)ptr)[0]);
break;
case 8:
#if UINTPTR_MAX == 0xffffffffffffffff
duk_push_pointer(ctx, (void*)((uint64_t*)ptr)[0]);
#else
return(ILibDuktape_Error(ctx, "GenericMarshal.get(): Cannot get 64bit value on 32bit platform"));
#endif
break;
default:
duk_push_int(ctx, 0);
break;
}
return 1;
}
duk_ret_t ILibDuktape_GenericMarshal_Variable_Val_SET(duk_context *ctx)
{
void *ptr;
int size;
int value = duk_require_int(ctx, 0);
duk_push_this(ctx); // [var]
duk_get_prop_string(ctx, -1, "_ptr"); // [var][ptr]
ptr = duk_to_pointer(ctx, -1);
duk_get_prop_string(ctx, -2, "_size"); // [var][ptr][size]
size = duk_to_int(ctx, -1);
switch (size)
{
case 2:
((unsigned short*)ptr)[0] = (unsigned short)value;
break;
case 4:
((unsigned int*)ptr)[0] = (unsigned int)value;
break;
default:
duk_push_string(ctx, "UNSUPPORTED VAL SIZE");
duk_throw(ctx);
return(DUK_RET_ERROR);
}
return 0;
}
duk_ret_t ILibDuktape_GenericMarshal_Variable_Deref(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
char *ptr;
//int size;
duk_push_this(ctx); // [var]
duk_get_prop_string(ctx, -1, "_ptr"); // [var][ptr]
ptr = (char*)duk_to_pointer(ctx, -1);
//duk_get_prop_string(ctx, -2, "_size"); // [var][ptr][size]
//size = duk_to_int(ctx, -1);
if (nargs < 2)
{
// Just Dereference Memory
ILibDuktape_GenericMarshal_Variable_PUSH(ctx, ((void**)ptr)[0], nargs == 1 ? duk_require_int(ctx, 0) : 0);
}
else
{
ILibDuktape_GenericMarshal_Variable_PUSH(ctx, (void*)(ptr + duk_require_int(ctx, 0)), duk_require_int(ctx, 1));
}
// We need to add a reference to the root variable, for memory management purposes
duk_push_this(ctx); // [deref][parent]
if (duk_has_prop_string(ctx, -1, "_root"))
{
// Parent Var is not the root, but has a reference to it
duk_get_prop_string(ctx, -1, "_root"); // [deref][parent][root]
duk_put_prop_string(ctx, -3, "_root"); // [deref][parent]
duk_pop(ctx); // [deref]
}
else
{
// Parent Var is the root
duk_put_prop_string(ctx, -2, "_root"); // [deref]
}
return 1;
}
duk_ret_t ILibDuktape_GenericMarshal_Variable_GetEx(duk_context *ctx)
{
int varSize = 0;
void *ptr;
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "_VarSize"); // [func][varSize]
varSize = duk_to_int(ctx, -1);
duk_push_this(ctx); // [func][varSize][var]
duk_get_prop_string(ctx, -1, "_ptr"); // [func][varSize][var][ptr]
ptr = duk_to_pointer(ctx, -1);
switch (varSize)
{
case 2:
duk_push_int(ctx, (int)((unsigned short*)ptr)[0]);
break;
case 4:
duk_push_int(ctx, (int)((unsigned int*)ptr)[0]);
break;
default:
duk_push_string(ctx, "Invalid Variable"); duk_throw(ctx); return(DUK_RET_ERROR);
}
return 1;
}
duk_ret_t ILibDuktape_GenericMarshal_Variable_SetEx(duk_context *ctx)
{
int varSize = 0;
void *ptr;
int newVal = duk_require_int(ctx, 0);
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "_VarSize"); // [func][varSize]
varSize = duk_to_int(ctx, -1);
duk_push_this(ctx); // [func][varSize][var]
duk_get_prop_string(ctx, -1, "_ptr"); // [func][varSize][var][ptr]
ptr = duk_to_pointer(ctx, -1);
switch (varSize)
{
case 2:
((unsigned short*)ptr)[0] = (unsigned short)newVal;
break;
case 4:
((unsigned int*)ptr)[0] = (unsigned int)newVal;
break;
default:
duk_push_string(ctx, "Invalid Variable"); duk_throw(ctx); return(DUK_RET_ERROR);
}
return 0;
}
void ILibDuktape_GenericMarshal_Variable_PUSH(duk_context *ctx, void *ptr, int size)
{
duk_push_object(ctx); // [var]
duk_push_pointer(ctx, ptr); // [var][ptr]
duk_put_prop_string(ctx, -2, "_ptr"); // [var]
duk_push_int(ctx, size); // [var][size]
duk_put_prop_string(ctx, -2, "_size"); // [var]
ILibDuktape_CreateEventWithGetterAndSetterEx(ctx, "Val", ILibDuktape_GenericMarshal_Variable_Val_GET, ILibDuktape_GenericMarshal_Variable_Val_SET);
ILibDuktape_CreateEventWithGetterAndSetterWithIntMetaData(ctx, "_VarSize", 4, "IntVal", ILibDuktape_GenericMarshal_Variable_GetEx, ILibDuktape_GenericMarshal_Variable_SetEx);
ILibDuktape_CreateEventWithGetterAndSetterWithIntMetaData(ctx, "_VarSize", 2, "ShortVal", ILibDuktape_GenericMarshal_Variable_GetEx, ILibDuktape_GenericMarshal_Variable_SetEx);
ILibDuktape_CreateInstanceMethod(ctx, "Deref", ILibDuktape_GenericMarshal_Variable_Deref, DUK_VARARGS);
ILibDuktape_CreateEventWithGetter(ctx, "String", ILibDuktape_GenericMarshal_Variable_Val_STRING);
ILibDuktape_CreateEventWithGetter(ctx, "AnsiString", ILibDuktape_GenericMarshal_Variable_Val_ASTRING);
ILibDuktape_CreateEventWithGetter(ctx, "HexString", ILibDuktape_GenericMarshal_Variable_Val_HSTRING);
ILibDuktape_CreateEventWithGetter(ctx, "HexString2", ILibDuktape_GenericMarshal_Variable_Val_HSTRING2);
}
duk_ret_t ILibDuktape_GenericMarshal_Variable_Finalizer(duk_context *ctx)
{
void *ptr = NULL;
if (duk_has_prop_string(ctx, 0, "_ptr"))
{
duk_get_prop_string(ctx, 0, "_ptr");
ptr = duk_to_pointer(ctx, -1);
if (ptr != NULL)
{
free(ptr);
duk_del_prop_string(ctx, 0, "_ptr");
}
}
return 0;
}
duk_ret_t ILibDuktape_GenericMarshal_CreateVariable(duk_context *ctx)
{
char* ptr;
int size = duk_require_int(ctx, 0);
ptr = (char*)ILibMemory_Allocate(size, 0, NULL, NULL);
ILibDuktape_GenericMarshal_Variable_PUSH(ctx, ptr, size); // [var]
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_GenericMarshal_Variable_Finalizer);
return 1;
}
void ILibDuktape_GenericMarshal_CallbackProxy_NativeSink_0()
{
}
void ILibDuktape_GenericMarshal_CallbackProxy_NativeSink_1(PTRSIZE v1)
{
Duktape_GenericMarshal_Proxy *user = (Duktape_GenericMarshal_Proxy*)v1;
duk_push_heapptr(user->ctx, user->jsCallbackPtr); // [func]
duk_push_heapptr(user->ctx, user->jsProxyObject); // [func][this]
if (duk_pcall_method(user->ctx, 0) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(user->ctx);
}
duk_pop(user->ctx); // ...
}
void ILibDuktape_GenericMarshal_CallbackProxy_NativeSink_2(PTRSIZE v1, PTRSIZE v2)
{
Duktape_GenericMarshal_Proxy *user = (Duktape_GenericMarshal_Proxy*)v2;
duk_push_heapptr(user->ctx, user->jsCallbackPtr); // [func]
duk_push_heapptr(user->ctx, user->jsProxyObject); // [func][this]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v1, sizeof(PTRSIZE)); // [func][this][v1]
if(duk_pcall_method(user->ctx, 1)!=0) // [retVal]
{
ILibDuktape_Process_UncaughtException(user->ctx);
}
duk_pop(user->ctx); // ...
}
void ILibDuktape_GenericMarshal_CallbackProxy_NativeSink_3(PTRSIZE v1, PTRSIZE v2, PTRSIZE v3)
{
Duktape_GenericMarshal_Proxy *user = (Duktape_GenericMarshal_Proxy*)v3;
duk_push_heapptr(user->ctx, user->jsCallbackPtr); // [func]
duk_push_heapptr(user->ctx, user->jsProxyObject); // [func][this]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v1, sizeof(PTRSIZE)); // [func][this][v1]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v2, sizeof(PTRSIZE)); // [func][this][v1][v2]
if(duk_pcall_method(user->ctx, 2)!=0) // [retVal]
{
ILibDuktape_Process_UncaughtException(user->ctx);
}
duk_pop(user->ctx); // ...
}
void ILibDuktape_GenericMarshal_CallbackProxy_NativeSink_4(PTRSIZE v1, PTRSIZE v2, PTRSIZE v3, PTRSIZE v4)
{
Duktape_GenericMarshal_Proxy *user = (Duktape_GenericMarshal_Proxy*)v4;
duk_push_heapptr(user->ctx, user->jsCallbackPtr); // [func]
duk_push_heapptr(user->ctx, user->jsProxyObject); // [func][this]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v1, sizeof(PTRSIZE)); // [func][this][v1]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v2, sizeof(PTRSIZE)); // [func][this][v1][v2]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v3, sizeof(PTRSIZE)); // [func][this][v1][v2][v3]
if(duk_pcall_method(user->ctx, 3)!=0) // [retVal]
{
ILibDuktape_Process_UncaughtException(user->ctx);
}
duk_pop(user->ctx); // ...
}
void ILibDuktape_GenericMarshal_CallbackProxy_NativeSink_5(PTRSIZE v1, PTRSIZE v2, PTRSIZE v3, PTRSIZE v4, PTRSIZE v5)
{
Duktape_GenericMarshal_Proxy *user = (Duktape_GenericMarshal_Proxy*)v5;
duk_push_heapptr(user->ctx, user->jsCallbackPtr); // [func]
duk_push_heapptr(user->ctx, user->jsProxyObject); // [func][this]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v1, sizeof(PTRSIZE)); // [func][this][v1]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v2, sizeof(PTRSIZE)); // [func][this][v1][v2]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v3, sizeof(PTRSIZE)); // [func][this][v1][v2][v3]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v4, sizeof(PTRSIZE)); // [func][this][v1][v2][v3][v4]
if(duk_pcall_method(user->ctx, 4)!=0) // [retVal]
{
ILibDuktape_Process_UncaughtException(user->ctx);
}
duk_pop(user->ctx); // ...
}
void ILibDuktape_GenericMarshal_CallbackProxy_NativeSink_6(PTRSIZE v1, PTRSIZE v2, PTRSIZE v3, PTRSIZE v4, PTRSIZE v5, PTRSIZE v6)
{
Duktape_GenericMarshal_Proxy *user = (Duktape_GenericMarshal_Proxy*)v6;
duk_push_heapptr(user->ctx, user->jsCallbackPtr); // [func]
duk_push_heapptr(user->ctx, user->jsProxyObject); // [func][this]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v1, sizeof(PTRSIZE)); // [func][this][v1]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v2, sizeof(PTRSIZE)); // [func][this][v1][v2]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v3, sizeof(PTRSIZE)); // [func][this][v1][v2][v3]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v4, sizeof(PTRSIZE)); // [func][this][v1][v2][v3][v4]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v5, sizeof(PTRSIZE)); // [func][this][v1][v2][v3][v4][v5]
if(duk_pcall_method(user->ctx, 5)!=0) // [retVal]
{
ILibDuktape_Process_UncaughtException(user->ctx);
}
duk_pop(user->ctx);
}
void ILibDuktape_GenericMarshal_CallbackProxy_NativeSink_7(PTRSIZE v1, PTRSIZE v2, PTRSIZE v3, PTRSIZE v4, PTRSIZE v5, PTRSIZE v6, PTRSIZE v7)
{
Duktape_GenericMarshal_Proxy *user = (Duktape_GenericMarshal_Proxy*)v7;
duk_push_heapptr(user->ctx, user->jsCallbackPtr); // [func]
duk_push_heapptr(user->ctx, user->jsProxyObject); // [func][this]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v1, sizeof(PTRSIZE)); // [func][this][v1]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v2, sizeof(PTRSIZE)); // [func][this][v1][v2]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v3, sizeof(PTRSIZE)); // [func][this][v1][v2][v3]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v4, sizeof(PTRSIZE)); // [func][this][v1][v2][v3][v4]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v5, sizeof(PTRSIZE)); // [func][this][v1][v2][v3][v4][v5]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v6, sizeof(PTRSIZE)); // [func][this][v1][v2][v3][v4][v5][v6]
if(duk_pcall_method(user->ctx, 6)!=0) // [retVal]
{
ILibDuktape_Process_UncaughtException(user->ctx);
}
duk_pop(user->ctx);
}
void ILibDuktape_GenericMarshal_CallbackProxy_NativeSink_8(PTRSIZE v1, PTRSIZE v2, PTRSIZE v3, PTRSIZE v4, PTRSIZE v5, PTRSIZE v6, PTRSIZE v7, PTRSIZE v8)
{
Duktape_GenericMarshal_Proxy *user = (Duktape_GenericMarshal_Proxy*)v8;
duk_push_heapptr(user->ctx, user->jsCallbackPtr); // [func]
duk_push_heapptr(user->ctx, user->jsProxyObject); // [func][this]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v1, sizeof(PTRSIZE)); // [func][this][v1]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v2, sizeof(PTRSIZE)); // [func][this][v1][v2]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v3, sizeof(PTRSIZE)); // [func][this][v1][v2][v3]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v4, sizeof(PTRSIZE)); // [func][this][v1][v2][v3][v4]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v5, sizeof(PTRSIZE)); // [func][this][v1][v2][v3][v4][v5]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v6, sizeof(PTRSIZE)); // [func][this][v1][v2][v3][v4][v5][v6]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v7, sizeof(PTRSIZE)); // [func][this][v1][v2][v3][v4][v5][v6][v7]
if(duk_pcall_method(user->ctx, 7)!=0) // [retVal]
{
ILibDuktape_Process_UncaughtException(user->ctx);
}
duk_pop(user->ctx);
}
void ILibDuktape_GenericMarshal_CallbackProxy_NativeSink_9(PTRSIZE v1, PTRSIZE v2, PTRSIZE v3, PTRSIZE v4, PTRSIZE v5, PTRSIZE v6, PTRSIZE v7, PTRSIZE v8, PTRSIZE v9)
{
Duktape_GenericMarshal_Proxy *user = (Duktape_GenericMarshal_Proxy*)v9;
duk_push_heapptr(user->ctx, user->jsCallbackPtr); // [func]
duk_push_heapptr(user->ctx, user->jsProxyObject); // [func][this]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v1, sizeof(PTRSIZE)); // [func][this][v1]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v2, sizeof(PTRSIZE)); // [func][this][v1][v2]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v3, sizeof(PTRSIZE)); // [func][this][v1][v2][v3]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v4, sizeof(PTRSIZE)); // [func][this][v1][v2][v3][v4]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v5, sizeof(PTRSIZE)); // [func][this][v1][v2][v3][v4][v5]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v6, sizeof(PTRSIZE)); // [func][this][v1][v2][v3][v4][v5][v6]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v7, sizeof(PTRSIZE)); // [func][this][v1][v2][v3][v4][v5][v6][v7]
ILibDuktape_GenericMarshal_Variable_PUSH(user->ctx, (void*)v8, sizeof(PTRSIZE)); // [func][this][v1][v2][v3][v4][v5][v6][v7][v8]
if(duk_pcall_method(user->ctx, 8)!=0) // [retVal]
{
ILibDuktape_Process_UncaughtException(user->ctx);
}
duk_pop(user->ctx);
}
duk_ret_t ILibDuktape_GenericMashal_CallbackProxy_Callback(duk_context *ctx)
{
int parms;
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "_numParms");
parms = duk_to_int(ctx, -1);
switch (parms)
{
case 0:
duk_push_pointer(ctx, (void*)ILibDuktape_GenericMarshal_CallbackProxy_NativeSink_0);
break;
case 1:
duk_push_pointer(ctx, (void*)ILibDuktape_GenericMarshal_CallbackProxy_NativeSink_1);
break;
case 2:
duk_push_pointer(ctx, (void*)ILibDuktape_GenericMarshal_CallbackProxy_NativeSink_2);
break;
case 3:
duk_push_pointer(ctx, (void*)ILibDuktape_GenericMarshal_CallbackProxy_NativeSink_3);
break;
case 4:
duk_push_pointer(ctx, (void*)ILibDuktape_GenericMarshal_CallbackProxy_NativeSink_4);
break;
case 5:
duk_push_pointer(ctx, (void*)ILibDuktape_GenericMarshal_CallbackProxy_NativeSink_5);
break;
case 6:
duk_push_pointer(ctx, (void*)ILibDuktape_GenericMarshal_CallbackProxy_NativeSink_6);
break;
case 7:
duk_push_pointer(ctx, (void*)ILibDuktape_GenericMarshal_CallbackProxy_NativeSink_7);
break;
case 8:
duk_push_pointer(ctx, (void*)ILibDuktape_GenericMarshal_CallbackProxy_NativeSink_8);
break;
case 9:
duk_push_pointer(ctx, (void*)ILibDuktape_GenericMarshal_CallbackProxy_NativeSink_9);
break;
default:
duk_push_string(ctx, "More than 9 parameters in the callback isn't supported yet");
duk_throw(ctx);
return(DUK_RET_ERROR);
break;
}
return 1;
}
duk_ret_t ILibDuktape_GenericMashal_CallbackProxy_State(duk_context *ctx)
{
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "_statePtr");
return 1;
}
duk_ret_t ILibDuktape_GenericMarshal_CreateCallbackProxy(duk_context *ctx)
{
Duktape_GenericMarshal_Proxy *ptr;
duk_push_object(ctx); // [proxy]
duk_push_fixed_buffer(ctx, sizeof(Duktape_GenericMarshal_Proxy)); // [proxy][buffer]
ptr = (Duktape_GenericMarshal_Proxy*)Duktape_GetBuffer(ctx, -1, NULL);
memset(ptr, 0, sizeof(Duktape_GenericMarshal_Proxy));
duk_put_prop_string(ctx, -2, "_buffer"); // [proxy]
duk_dup(ctx, 1); // [proxy][parms]
duk_put_prop_string(ctx, -2, "_numParms"); // [proxy]
duk_push_pointer(ctx, ptr); // [proxy][statePtr]
duk_put_prop_string(ctx, -2, "_statePtr"); // [proxy]
ptr->ctx = ctx;
ptr->jsCallbackPtr = (void*)duk_require_heapptr(ctx, 0);
ptr->jsProxyObject = (void*)duk_get_heapptr(ctx, -1);
duk_dup(ctx, 0); // [proxy][jsCallback]
duk_put_prop_string(ctx, -2, "_jsCallback"); // [proxy]
ILibDuktape_CreateEventWithGetter(ctx, "Callback", ILibDuktape_GenericMashal_CallbackProxy_Callback);
ILibDuktape_CreateEventWithGetter(ctx, "State", ILibDuktape_GenericMashal_CallbackProxy_State);
return 1;
}
duk_ret_t ILibDuktape_GenericMarshal_MethodInvoke(duk_context *ctx)
{
void *fptr = NULL;
int parms = duk_get_top(ctx);
int i;
PTRSIZE vars[10];
int retVal = -1;
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "_address"); // [func][addr]
fptr = duk_to_pointer(ctx, -1);
if (fptr == NULL)
{
duk_push_string(ctx, "INVALID METHOD");
duk_throw(ctx);
return(DUK_RET_ERROR);
}
for (i = 0; i < parms; ++i)
{
if (duk_is_object(ctx, i))
{
duk_get_prop_string(ctx, i, "_ptr");
vars[i] = (PTRSIZE)duk_to_pointer(ctx, -1);
}
else if (duk_is_number(ctx, i))
{
vars[i] = (PTRSIZE)duk_require_int(ctx, i);
}
else if (duk_is_pointer(ctx, i))
{
vars[i] = (PTRSIZE)duk_require_pointer(ctx, i);
}
else
{
duk_push_string(ctx, "INVALID PARAMETER");
duk_throw(ctx);
return(DUK_RET_ERROR);
}
}
switch (parms)
{
case 0:
retVal = (int)((R0)fptr)();
break;
case 1:
retVal = (int)((R1)fptr)(vars[0]);
break;
case 2:
retVal = (int)((R2)fptr)(vars[0], vars[1]);
break;
case 3:
retVal = (int)((R3)fptr)(vars[0], vars[1], vars[2]);
break;
case 4:
retVal = (int)((R4)fptr)(vars[0], vars[1], vars[2], vars[3]);
break;
case 5:
retVal = (int)((R5)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4]);
break;
case 6:
retVal = (int)((R6)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5]);
break;
case 7:
retVal = (int)((R7)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6]);
break;
case 8:
retVal = (int)((R8)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7]);
break;
case 9:
retVal = (int)((R9)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8]);
break;
case 10:
retVal = (int)((R10)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9]);
break;
default:
duk_push_string(ctx, "INVALID NUMBER OF PARAMETERS, MAX of 10");
duk_throw(ctx);
return(DUK_RET_ERROR);
}
duk_push_int(ctx, retVal);
return 1;
}
duk_ret_t ILibDuktape_GenericMarshal_CreateMethod(duk_context *ctx)
{
void* module = NULL;
char* funcName = (char*)duk_require_string(ctx, 0);
void* funcAddress = NULL;
char* exposedMethod = duk_get_top(ctx) == 1 ? funcName : (char*)duk_require_string(ctx, 1);
duk_push_this(ctx); // [obj]
duk_get_prop_string(ctx, -1, "_moduleAddress"); // [obj][module]
module = duk_to_pointer(ctx, -1);
duk_pop(ctx); // [obj]
#ifdef WIN32
funcAddress = (void*)GetProcAddress((HMODULE)module, (LPCSTR)funcName);
#else
funcAddress = (void*)dlsym(module, funcName);
#endif
if (funcAddress == NULL)
{
char errstr[4096];
sprintf_s(errstr, sizeof(errstr), "CreateMethod Error: Method Name [%s] Not Found", funcName);
duk_push_string(ctx, errstr);
duk_throw(ctx);
return(DUK_RET_ERROR);
}
duk_push_c_function(ctx, ILibDuktape_GenericMarshal_MethodInvoke, DUK_VARARGS); // [obj][func]
duk_push_pointer(ctx, funcAddress); // [obj][func][addr]
duk_put_prop_string(ctx, -2, "_address"); // [obj][func]
duk_put_prop_string(ctx, -2, exposedMethod); // [obj]
return 0;
}
duk_ret_t ILibDuktape_GenericMarshal_CreateNativeProxy(duk_context *ctx)
{
void* module = NULL;
char* libName = duk_is_string(ctx, 0) ? (char*)duk_require_string(ctx, 0) : NULL;
#ifdef WIN32
module = (void*)LoadLibraryA((LPCSTR)libName);
#else
module = dlopen(libName, RTLD_NOW);
#endif
if (module == NULL)
{
#ifdef WIN32
duk_push_string(ctx, "Could not create Native Proxy");
#else
duk_push_string(ctx, dlerror());
#endif
duk_throw(ctx);
return(DUK_RET_ERROR);
}
duk_push_object(ctx); // [obj]
duk_push_pointer(ctx, module); // [obj][module]
duk_put_prop_string(ctx, -2, "_moduleAddress"); // [obj]
ILibDuktape_CreateInstanceMethod(ctx, "CreateMethod", ILibDuktape_GenericMarshal_CreateMethod, DUK_VARARGS); // [obj]
return 1;
}
duk_ret_t ILibDuktape_GenericMarshal_CreateVariableEx(duk_context *ctx)
{
char* ptr;
int size;
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "_VarSize"); // [func][size]
size = duk_to_int(ctx, -1);
ptr = (char*)ILibMemory_Allocate(size, 0, NULL, NULL);
ILibDuktape_GenericMarshal_Variable_PUSH(ctx, ptr, size); // [func][size][var]
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_GenericMarshal_Variable_Finalizer);
return 1;
}
void ILibDuktape_GenericMarshal_Push(duk_context *ctx, void *chain)
{
duk_push_object(ctx); // [obj]
ILibDuktape_CreateInstanceMethod(ctx, "CreateVariable", ILibDuktape_GenericMarshal_CreateVariable, 1);
ILibDuktape_CreateInstanceMethod(ctx, "CreateCallbackProxy", ILibDuktape_GenericMarshal_CreateCallbackProxy, 2);
ILibDuktape_CreateInstanceMethod(ctx, "CreateNativeProxy", ILibDuktape_GenericMarshal_CreateNativeProxy, 1);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "_VarSize", 4, "CreateInteger", ILibDuktape_GenericMarshal_CreateVariableEx, 0);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "_VarSize", ((int)sizeof(void*)), "CreatePointer", ILibDuktape_GenericMarshal_CreateVariableEx, 0);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "_VarSize", 2, "CreateShort", ILibDuktape_GenericMarshal_CreateVariableEx, 0);
}
void ILibDuktape_GenericMarshal_init(duk_context *ctx)
{
ILibDuktape_ModSearch_AddHandler(ctx, "_GenericMarshal", ILibDuktape_GenericMarshal_Push);
}
#ifdef __DOXY__
/*!
\brief Helper class, similar to <b>'FFI'</b> that allows JavaScript to make native calls. <b>Note:</b> To use, must <b>require('_GenericMarshal')</b>
*/
class _GenericMarshal
{
public:
/*!
\brief Creates a NativeProxy object for the given <b>dll</b> or <b>.so</b> file.
\param path \<String\> The <b>dll</b> or <b>.so</b> file name or path. For example, 'wlanapi.dll'
\return <NativeProxy> NativeProxy abstraction object to use for method invocation.
*/
NativeProxy CreateNativeProxy(path);
/*!
\brief Create a NativeCallbackProxy object that can be used with a NativeProxy object for callback reception. <b>Note:</b> The last parameter of the native callback must be an opaque user state object/ptr.
\param func The function to dispatch on callback
\param numVars The number of parameters in the native callback function signature
\return <NativeCallbackProxy> NativeCallbackProxy object to use for native callback reception.
*/
NativeCallbackProxy CreateCallbackProxy(func, numVars);
/*!
\brief Initializes a proxy variable to use with a NativeProxy object.
\param sz <Integer> Amount of memory in bytes to initialize
\return <NativeVariable> NativeVariable object to use with NativeProxy object method calls.
*/
NativeVariable CreateVariable(sz);
/*!
\brief Initializes an integer (4 bytes) as a proxy variable to use with a NativeProxy object.
\return <NativeVariable> NativeVariable object to use with NativeProxy object method calls.
*/
NativeVariable CreateInteger();
/*!
\brief Initializes an short (2 bytes) as a proxy variable to use with a NativeProxy object.
\return <NativeVariable> NativeVariable object to use with NativeProxy object method calls.
*/
NativeVariable CreateShort();
/*!
\brief Initializes a pointer as a proxy variable to use with a NativeProxy object. The size used is the actual size of a void* pointer.
\return <NativeVariable> NativeVariable object to use with NativeProxy object method calls.
*/
NativeVariable CreatePointer();
/*!
\brief Variable abstraction used by NativeProxy and NativeCallbackProxy
*/
class NativeVariable
{
public:
/*!
\brief GET/SET property. 64 bit values are only supported on 64 bit builds. 2 and 4 bytes values are passed as int. 8 byte value passes as a pointer.
*/
void Val;
/*!
\brief GET/SET 4 byte integer property.
*/
void IntVal;
/*!
\brief GET/SET 2 byte short property.
*/
void ShortVal;
/*!
\brief Dereferences the specified memory region
*
NativeVariable Deref([offset], length);
\param offset <integer> Optional offset, specifying where to start dereferencing. 0 if not specified.
\param length <integer> The number of bytes to dereference
\return <NativeVariable> NativeVariable object representing the dereferenced memory.
*/
NativeVariable Deref([offset], length);
/*!
\brief Property GET that returns memory as a simple string
\return \<String\>
*/
object String;
/*!
\brief Property GET that returns memory as a simple string. <b>Note:</b> On Win32, this will perform a Wide to Ansi conversion.
\return \<String\>
*/
object AnsiString;
/*!
\brief Property GET that returns memory as a Hex String of bytes (ie AABBCCDD)
\return \<String\>
*/
object HexString;
/*!
\brief Property GET that returns memory as a Colon delimited Hex String of bytes (ie AA:BB:CC:DD)
\return \<String\>
*/
object HexString2;
};
/*!
\brief JavaScript abstraction object for a Native library. <b>Note:</b> Must call 'CreateMethod' to add instance methods, that will dispatch into the native library.
*/
class NativeProxy
{
public:
/*!
\brief Adds an instance method, that will proxy method calls into Native.
\param methodName \<String\> The name of the exposed method to proxy
\param newMethodName \<String\> The name of the instance method to add to the NativeProxy object. If not specified, the name specified by 'methodName' will be used.
*/
void CreateMethod(methodName[, newMethodName]);
};
/*!
\brief JavaScript abstraction to proxy callbacks between Native and JavaScript, using NativeProxy
*/
class NativeCallbackProxy
{
public:
/*!
\brief JavaScript dispatcher that should be passed as the callback function pointer when invoking a native method using NativeProxy
\return NativeVariable object that proxies the callback, which should be passed as the callback function when invoking a method with NativeProxy
*/
NativeVariable Callback;
/*!
\brief NativeVariable encapsulation of JavaScript dispatcher data, that must be passed as 'opaque user data' when invoking a method with NativeProxy <b>Note:</b> The callback signature must return this opaque data as the last parameter
\return NativeVariable object passed as 'opaque user data' that is used by the callback dispatcher.
*/
NativeVariable State;
};
};
#endif

View File

@@ -0,0 +1,26 @@
/*
Copyright 2006 - 2017 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 __DuktapeGenericMarshal__
#define __DuktapeGenericMarshal__
#include "duktape.h"
void ILibDuktape_GenericMarshal_init(duk_context *ctx);
#endif

View File

@@ -0,0 +1,595 @@
/*
Copyright 2006 - 2017 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>
#endif
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(_MINCORE)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif
#include "duktape.h"
#include "microstack/ILibParsers.h"
#include "ILibDuktape_Helpers.h"
#include "ILibParsers_Duktape.h"
#include "microstack/ILibCrypto.h"
#include "ILibDuktape_EventEmitter.h"
char stash_key[32];
struct sockaddr_in6 duktape_internalAddress;
#define ILibDuktape_EventEmitter_Table "\xFF_EventEmitterTable"
#define ILibDuktape_Process_ExitCode "\xFF_ExitCode"
#define ILibDuktape_Memory_AllocTable "\xFF_MemoryAllocTable"
duk_ret_t ILibDuktape_Error(duk_context *ctx, char *format, ...)
{
char dest[4096];
int len = 0;
va_list argptr;
va_start(argptr, format);
len += vsnprintf(dest + len, sizeof(dest) - len, format, argptr);
va_end(argptr);
duk_push_string(ctx, dest);
duk_throw(ctx);
return DUK_RET_ERROR;
}
int Duktape_GetBooleanProperty(duk_context *ctx, duk_idx_t i, char *propertyName, int defaultValue)
{
int retVal = defaultValue;
if (duk_has_prop_string(ctx, i, propertyName))
{
duk_get_prop_string(ctx, i, propertyName);
retVal = (int)duk_get_boolean(ctx, -1);
duk_pop(ctx);
}
return retVal;
}
void *Duktape_GetHeapptrProperty(duk_context *ctx, duk_idx_t i, char* propertyName)
{
void *retVal = NULL;
if (duk_has_prop_string(ctx, i, propertyName))
{
duk_get_prop_string(ctx, i, propertyName);
retVal = duk_get_heapptr(ctx, -1);
duk_pop(ctx);
}
return retVal;
}
void *Duktape_GetPointerProperty(duk_context *ctx, duk_idx_t i, char* propertyName)
{
void *retVal = NULL;
if (duk_has_prop_string(ctx, i, propertyName))
{
duk_get_prop_string(ctx, i, propertyName);
retVal = duk_to_pointer(ctx, -1);
duk_pop(ctx);
}
return retVal;
}
char* Duktape_GetStringPropertyValueEx(duk_context *ctx, duk_idx_t i, char* propertyName, char* defaultValue, duk_size_t *len)
{
char *retVal = defaultValue;
if (duk_has_prop_string(ctx, i, propertyName))
{
duk_get_prop_string(ctx, i, propertyName);
retVal = (char*)duk_get_lstring(ctx, -1, len);
duk_pop(ctx);
}
else
{
if (len != NULL) { *len = (defaultValue == NULL) ? 0 : strnlen_s(defaultValue, sizeof(ILibScratchPad)); }
}
return retVal;
}
int Duktape_GetIntPropertyValue(duk_context *ctx, duk_idx_t i, char* propertyName, int defaultValue)
{
int retVal = defaultValue;
if (duk_has_prop_string(ctx, i, propertyName))
{
duk_get_prop_string(ctx, i, propertyName);
retVal = duk_to_int(ctx, -1);
duk_pop(ctx);
}
return retVal;
}
void Duktape_CreateEnum(duk_context *ctx, char* enumName, char** fieldNames, int * fieldValues, int numFields)
{
int i;
duk_push_global_object(ctx); // [global]
duk_push_object(ctx); // [global][obj]
for (i = 0; i < numFields; ++i)
{
duk_push_int(ctx, fieldValues[i]); // [global][obj][val]
duk_put_prop_string(ctx, -2, fieldNames[i]); // [global][obj]
}
duk_put_prop_string(ctx, -2, enumName); // [global]
duk_pop(ctx);
}
char *Duktape_GetStashKey(void* value)
{
sprintf_s(stash_key, sizeof(stash_key), "%p", value);
return((char*)stash_key);
}
char* Duktape_GetBuffer(duk_context *ctx, duk_idx_t i, duk_size_t *bufLen)
{
char *retVal = NULL;
if (bufLen != NULL) { *bufLen = 0; }
if (duk_is_string(ctx, i))
{
retVal = (char*)duk_get_lstring(ctx, i, bufLen);
}
else if (duk_is_buffer(ctx, i))
{
retVal = (char*)duk_require_buffer(ctx, i,bufLen);
}
else if(duk_is_buffer_data(ctx, i))
{
retVal = (char*)duk_require_buffer_data(ctx, i, bufLen);
}
else if (duk_is_object(ctx, i))
{
duk_json_encode(ctx, i);
retVal = (char*)duk_get_lstring(ctx, i, bufLen);
}
else
{
ILibDuktape_Error(ctx, "Duktape_GetBuffer(): Unknown parameter");
}
return retVal;
}
struct sockaddr_in6* Duktape_IPAddress4_FromString(char* address, unsigned short port)
{
memset(&duktape_internalAddress, 0, sizeof(struct sockaddr_in6));
duktape_internalAddress.sin6_family = AF_INET;
duktape_internalAddress.sin6_port = htons(port);
ILibInet_pton(AF_INET, address, &(((struct sockaddr_in*)&duktape_internalAddress)->sin_addr));
return(&duktape_internalAddress);
}
struct sockaddr_in6* Duktape_IPAddress6_FromString(char* address, unsigned short port)
{
memset(&duktape_internalAddress, 0, sizeof(struct sockaddr_in6));
duktape_internalAddress.sin6_family = AF_INET6;
duktape_internalAddress.sin6_port = htons(port);
ILibInet_pton(AF_INET6, address, &(duktape_internalAddress.sin6_addr));
return(&duktape_internalAddress);
}
void ILibDuktape_SockAddrToOptions(duk_context *ctx, struct sockaddr_in6 *addr)
{
char *str = ILibInet_ntop2((struct sockaddr*)addr, ILibScratchPad, sizeof(ILibScratchPad));
unsigned short port = ntohs(addr->sin6_port);
duk_push_object(ctx); // [options]
duk_push_string(ctx, str); // [options][host]
duk_put_prop_string(ctx, -2, "host"); // [options]
duk_push_int(ctx, (int)port); // [options][port]
duk_put_prop_string(ctx, -2, "port"); // [options]
}
duk_ret_t ILibDuktape_CreateEventWithSetter_SetterSink(duk_context *ctx)
{
void **ptr;
char *name;
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "_ptr"); // [func][ptr]
ptr = (void**)duk_to_pointer(ctx, -1); // [func][ptr]
duk_get_prop_string(ctx, -2, "_pname"); // [func][ptr][pname]
name = (char*)duk_to_string(ctx, -1); // [func][ptr][pname]
duk_push_this(ctx); // [obj]
duk_dup(ctx, 0); // [obj][handler]
duk_put_prop_string(ctx, -2, name); // [obj]
*ptr = !duk_is_null_or_undefined(ctx, 0) ? duk_require_heapptr(ctx, 0) : NULL;
return 0;
}
duk_ret_t ILibDuktape_CreateEventWithGetterExSink(duk_context *ctx)
{
duk_push_current_function(ctx);
duk_get_prop_string(ctx, -1, "\xFF_return");
return 1;
}
void ILibDuktape_CreateEventWithGetterEx(duk_context *ctx, char *propName, void *heapptr)
{
duk_push_string(ctx, propName); // [obj][prop]
duk_push_c_function(ctx, ILibDuktape_CreateEventWithGetterExSink, 1); // [obj][prop][func] // [obj][prop][getFunc]
duk_push_heapptr(ctx, heapptr); // [obj][prop][func][ptr]
duk_put_prop_string(ctx, -2, "\xFF_return"); // [obj][prop][func]
duk_def_prop(ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_GETTER); // [obj]
}
void ILibDuktape_CreateEventWithGetter(duk_context *ctx, char *propName, duk_c_function getterMethod)
{
duk_push_string(ctx, propName); // [obj][prop]
duk_push_c_function(ctx, getterMethod, 1); // [obj][prop][getFunc]
duk_def_prop(ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_GETTER); // [obj]
}
void ILibDuktape_CreateEventWithGetterAndSetterEx(duk_context *ctx, char *propName, duk_c_function getterMethod, duk_c_function setterMethod)
{
duk_push_string(ctx, propName); // [obj][prop]
duk_push_c_function(ctx, getterMethod, 1); // [obj][prop][getFunc]
duk_push_c_function(ctx, setterMethod, 1); // [obj][prop][getFunc][setFunc]
duk_def_prop(ctx, -4, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER); // [obj]
}
void ILibDuktape_CreateEventWithGetterAndSetterWithMetaData(duk_context *ctx, char* metaDataPropName, duk_idx_t metaDataPropIndex, char *propName, duk_c_function getterMethod, duk_c_function setterMethod)
{
duk_dup(ctx, metaDataPropIndex); // [obj][metaData]
if (metaDataPropIndex < 0)
{
duk_remove(ctx, metaDataPropIndex - 1);
}
duk_push_string(ctx, propName); // [obj][metaData][prop]
duk_swap_top(ctx, -2); // [obj][prop][metaData]
duk_push_c_function(ctx, getterMethod, 1); // [obj][prop][metaData][getFunc]
duk_swap_top(ctx, -2); // [obj][prop][getFunc][metaData]
duk_dup(ctx, -1); // [obj][prop][getFunc][metaData][metaData]
duk_put_prop_string(ctx, -3, metaDataPropName); // [obj][prop][getFunc][metaData]
duk_push_c_function(ctx, setterMethod, 1); // [obj][prop][getFunc][metaData][setFunc]
duk_swap_top(ctx, -2); // [obj][prop][getFunc][setFunc][metaData]
duk_put_prop_string(ctx, -2, metaDataPropName); // [obj][prop][getFunc][setFunc]
duk_def_prop(ctx, -4, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER); // [obj]
}
void ILibDuktape_CreateEventWithGetterAndSetter(duk_context *ctx, char *propName, char *propNamePtr, void **hptr, duk_c_function getterMethod)
{
duk_push_string(ctx, propName); // [obj][prop]
duk_push_c_function(ctx, getterMethod, 1); // [obj][prop][getFunc]
duk_push_c_function(ctx, ILibDuktape_CreateEventWithSetter_SetterSink, 1); // [obj][prop][getFunc][setFunc]
duk_push_pointer(ctx, hptr); // [obj][prop][getFunc][setFunc][ptr]
duk_put_prop_string(ctx, -2, "_ptr"); // [obj][prop][getFunc][setFunc]
duk_push_string(ctx, propNamePtr); // [obj][prop][getFunc][setFunc][name]
duk_put_prop_string(ctx, -2, "_pname"); // [obj][prop][getFunc][setFunc]
duk_def_prop(ctx, -4, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER); // [obj]
}
void ILibDuktape_CreateEventWithSetterEx(duk_context *ctx, char *propName, duk_c_function setterMethod)
{
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_def_prop(ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_SETTER); // [obj]
}
void ILibDuktape_CreateEventWithSetter(duk_context *ctx, char *propName, char *propNamePtr, void **hptr)
{
duk_push_string(ctx, propName); // [obj][setter]
duk_push_c_function(ctx, ILibDuktape_CreateEventWithSetter_SetterSink, 1); // [obj][setter][func]
duk_push_pointer(ctx, hptr); // [obj][setter][func][ptr]
duk_put_prop_string(ctx, -2, "_ptr"); // [obj][setter][func]
duk_push_string(ctx, propNamePtr); // [obj][setter][func][name]
duk_put_prop_string(ctx, -2, "_pname"); // [obj][setter][func]
duk_def_prop(ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_SETTER); // [obj]
}
duk_ret_t ILibDuktape_Helper_AddHeapFinalizerSink(duk_context *ctx)
{
ILibDuktape_HelperEvent handler;
void *user;
duk_dup(ctx, 0); // [obj]
duk_get_prop_string(ctx, -1, "handler"); // [obj][handler]
handler = (ILibDuktape_HelperEvent)duk_get_pointer(ctx, -1);
duk_get_prop_string(ctx, -2, "user"); // [obj][handler][user]
user = duk_get_pointer(ctx, -1);
if (handler != NULL) { handler(ctx, user); }
return 0;
}
void ILibDuktape_Helper_AddHeapFinalizer(duk_context *ctx, ILibDuktape_HelperEvent handler, void *user)
{
char *key = Duktape_GetStashKey(user != NULL ? user : (void*)handler);
duk_push_heap_stash(ctx); // [g]
duk_push_object(ctx); // [g][obj]
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]
duk_put_prop_string(ctx, -2, "handler");// [g][obj]
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_Helper_AddHeapFinalizerSink);
duk_put_prop_string(ctx, -2, key); // [g]
duk_pop(ctx); // ...
}
int ILibDuktape_Process_GetExitCode(duk_context *ctx)
{
int retVal = 0;
duk_push_global_object(ctx); // [g]
if (duk_has_prop_string(ctx, -1, "process"))
{
duk_get_prop_string(ctx, -1, "process"); // [g][process]
if (duk_has_prop_string(ctx, -1, ILibDuktape_Process_ExitCode))
{
duk_get_prop_string(ctx, -1, ILibDuktape_Process_ExitCode); // [g][process][code]
retVal = (int)duk_get_int(ctx, -1);
duk_pop(ctx); // [g][process]
}
duk_pop(ctx); // [g]
}
duk_pop(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)
{
void *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 = duk_get_heapptr(ctx, -1);
duk_pop(ctx); // [g]
}
duk_pop(ctx); // ...
return retVal;
}
void ILibDuktape_SetNativeUncaughtExceptionHandler(duk_context * ctx, ILibDuktape_NativeUncaughtExceptionHandler handler, void * user)
{
void *j = ILibDuktape_GetProcessObject(ctx);
if (j != NULL)
{
duk_push_heapptr(ctx, j); // [process]
duk_push_pointer(ctx, handler); // [process][handler]
duk_put_prop_string(ctx, -2, ILibDuktape_NativeUncaughtExceptionPtr); // [process]
duk_push_pointer(ctx, user); // [process][user]
duk_put_prop_string(ctx, -2, ILibDuktape_NativeUncaughtExceptionUserPtr); // [process]
duk_pop(ctx); // ...
}
}
duk_ret_t ILibDuktape_Process_UncaughtExceptionExGetter(duk_context *ctx)
{
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "\xFF_customMessage");
return 1;
}
void ILibDuktape_Process_UncaughtExceptionEx(duk_context *ctx, char *format, ...)
{
char dest[4096];
int len = 0;
va_list argptr;
duk_size_t errmsgLen;
char *errmsg = (char*)duk_safe_to_lstring(ctx, -1, &errmsgLen);
void *j = ILibDuktape_GetProcessObject(ctx);
ILibDuktape_EventEmitter *emitter;
duk_push_heapptr(ctx, j); // [process]
emitter = ILibDuktape_EventEmitter_GetEmitter_fromCurrent(ctx);
duk_pop(ctx); // ...
va_start(argptr, format);
len += vsnprintf(dest + len, sizeof(dest) - len, format, argptr);
va_end(argptr);
if (errmsgLen + len < sizeof(dest))
{
len += sprintf_s(dest + len, sizeof(dest) - len, " => %s", errmsg);
}
if (j != NULL)
{
duk_push_heapptr(ctx, j); // [process]
if (duk_has_prop_string(ctx, -1, ILibDuktape_NativeUncaughtExceptionPtr))
{
duk_get_prop_string(ctx, -1, ILibDuktape_NativeUncaughtExceptionPtr); // [process][ptr]
duk_get_prop_string(ctx, -2, ILibDuktape_NativeUncaughtExceptionUserPtr); // [process][ptr][user]
((ILibDuktape_NativeUncaughtExceptionHandler)duk_get_pointer(ctx, -2))(ctx, (char*)dest, duk_get_pointer(ctx, -1));
duk_pop_2(ctx); // [process]
}
duk_pop(ctx); // ...
}
if (emitter != NULL)
{
duk_push_heapptr(emitter->ctx, emitter->object); // [process]
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_pcall_method(emitter->ctx, 2);
duk_pop(emitter->ctx); // ...
}
}
// Error MUST be at top of stack when calling this method
void ILibDuktape_Process_UncaughtException(duk_context *ctx)
{
ILibDuktape_Process_UncaughtExceptionEx(ctx, "");
}
char* Duktape_GetContextGuidHex(duk_context *ctx)
{
char *retVal = NULL;
char *guid;
duk_size_t guidLength;
int i;
duk_push_heap_stash(ctx); // [stash]
if (duk_has_prop_string(ctx, -1, CONTEXT_GUID_BUFFER))
{
duk_get_prop_string(ctx, -1, CONTEXT_GUID_BUFFER); // [stash][str]
guid = (char*)Duktape_GetBuffer(ctx, -1, &guidLength);
for (i = (int)guidLength-1; i > 1 && guid[i] == 0; --i)
{
}
util_tohex(guid, (int)guidLength, ILibScratchPad);
duk_pop(ctx); // [stash]
for (i = ((int)guidLength * 2) - 1; i > 1 && ILibScratchPad[i] == 48; --i)
{
}
retVal = ILibScratchPad;
retVal[i] = 0;
}
duk_pop(ctx); // ...
return retVal;
}
void *Duktape_GetChain(duk_context *ctx)
{
void *retVal = NULL;
duk_push_heap_stash(ctx); // [stash]
if (duk_has_prop_string(ctx, -1, ILibDuktape_Context_Chain))
{
duk_get_prop_string(ctx, -1, ILibDuktape_Context_Chain); // [stash][ptr]
retVal = duk_get_pointer(ctx, -1);
duk_pop_2(ctx); // ...
}
else
{
duk_pop(ctx); // ...
}
return retVal;
}
duk_ret_t ILibDuktape_ExternalEventEmitter(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
char *name = (char*)duk_require_string(ctx, 0);
void **hptr;
int i;
duk_push_this(ctx); // [obj]
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_Table); // [obj][table]
if (!duk_has_prop_string(ctx, -1, name))
{
return(ILibDuktape_Error(ctx, "ExternalEventEmitter(): Event '%s' not found", name));
}
duk_get_prop_string(ctx, -1, name); // [obj][table][ptr]
hptr = (void**)duk_get_pointer(ctx, -1);
if (*hptr != NULL)
{
duk_push_heapptr(ctx, *hptr); // [func]
duk_push_this(ctx); // [func][this]
for (i = 1; i < nargs; ++i)
{
duk_dup(ctx, i); // [func][this][...]
}
if (duk_pcall_method(ctx, nargs - 1) != 0) { ILibDuktape_Process_UncaughtException(ctx); }
duk_pop(ctx); // ...
}
return 0;
}
duk_ret_t ILibDuktape_IndependentFinalizer_Dispatch(duk_context *ctx)
{
ILibDuktape_IndependentFinalizerHandler handler;
duk_get_prop_string(ctx, 0, "ptr");
duk_get_prop_string(ctx, 0, "parent");
handler = (ILibDuktape_IndependentFinalizerHandler)duk_get_pointer(ctx, -2);
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);
}
duk_ret_t ILibDuktape_CreateProperty_InstanceMethod_Sink(duk_context *ctx)
{
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "actualFunc"); // [func][actualFunc]
return 1;
}
void ILibDuktape_CreateProperty_InstanceMethodEx(duk_context *ctx, char *methodName, void *funcHeapPtr)
{
duk_push_string(ctx, methodName); // [obj][prop]
duk_push_c_function(ctx, ILibDuktape_CreateProperty_InstanceMethod_Sink, 1); // [obj][prop][getFunc]
duk_push_heapptr(ctx, funcHeapPtr); // [obj][prop][getFunc][func]
duk_put_prop_string(ctx, -2, "actualFunc"); // [obj][prop][getFunc]
duk_def_prop(ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_GETTER); // [obj]
}
void ILibDuktape_CreateProperty_InstanceMethod(duk_context *ctx, char *methodName, duk_c_function impl, duk_idx_t argCount)
{
duk_push_string(ctx, methodName); // [obj][prop]
duk_push_c_function(ctx, ILibDuktape_CreateProperty_InstanceMethod_Sink, 1); // [obj][prop][getFunc]
duk_push_c_function(ctx, impl, argCount); // [obj][prop][getFunc][func]
duk_put_prop_string(ctx, -2, "actualFunc"); // [obj][prop][getFunc]
duk_def_prop(ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_GETTER); // [obj]
}
duk_ret_t ILibDuktape_ReadonlyProperty_Get(duk_context *ctx)
{
duk_push_current_function(ctx); // [getFunc]
duk_get_prop_string(ctx, -1, "\xFF_PropValue"); // [getFunc][value]
return 1;
}
void ILibDuktape_CreateReadonlyProperty(duk_context *ctx, char *propName)
{ // [obj][value]
duk_push_string(ctx, propName); // [obj][value][prop]
duk_swap_top(ctx, -2); // [obj][prop][value]
duk_push_c_function(ctx, ILibDuktape_ReadonlyProperty_Get, 1); // [obj][prop][value][getFunc]
duk_swap_top(ctx, -2); // [obj][prop][getFunc][value]
duk_put_prop_string(ctx, -2, "\xFF_PropValue"); // [obj][prop][getFunc]
duk_def_prop(ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_GETTER); // [obj]
}
void *ILibDuktape_Memory_Alloc(duk_context *ctx, duk_size_t size)
{
void *retVal = NULL;
duk_push_heap_stash(ctx); // [s]
if (!duk_has_prop_string(ctx, -1, ILibDuktape_Memory_AllocTable))
{
duk_push_object(ctx); // [s][table]
duk_dup(ctx, -1); // [s][table][table]
duk_put_prop_string(ctx, -3, ILibDuktape_Memory_AllocTable); // [s][table]
}
else
{
duk_get_prop_string(ctx, -1, ILibDuktape_Memory_AllocTable); // [s][table]
}
duk_push_fixed_buffer(ctx, size); // [s][table][buffer]
retVal = Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, Duktape_GetStashKey(retVal)); // [s][table]
duk_pop_2(ctx);
return(retVal);
}

View File

@@ -0,0 +1,86 @@
/*
Copyright 2006 - 2017 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_HELPERS___
#define ___ILIBDUKTAPE_HELPERS___
#include "duktape.h"
#ifndef MICROSTACK_NOTLS
#include <openssl/ssl.h>
#endif
typedef void(*ILibDuktape_HelperEvent)(duk_context *ctx, void *user);
#define ILibDuktape_NativeUncaughtExceptionPtr "\xFF_NativeUncaughtExceptionPtr"
#define ILibDuktape_NativeUncaughtExceptionUserPtr "\xFF_NativeUncaughtExceptionUserPtr"
#define ILibDuktape_MeshAgent_Cert_NonLeaf "\xFF_selfcert"
#define ILibDuktape_MeshAgent_Cert_Client "\xFF_selftlsclientcert"
#define ILibDuktape_MeshAgent_Cert_Server "\xFF_selftlscert"
#define CONTEXT_GUID_BUFFER "_CONTEXT_GUID"
#define ILibDuktape_Context_Chain "\xFF_chainptr"
char* Duktape_GetContextGuidHex(duk_context *ctx);
void *Duktape_GetChain(duk_context *ctx);
char *Duktape_GetStashKey(void* value);
char* Duktape_GetBuffer(duk_context *ctx, duk_idx_t i, duk_size_t *bufLen);
void Duktape_CreateEnum(duk_context *ctx, char* enumName, char** fieldNames, int * fieldValues, int numFields);
char* Duktape_GetStringPropertyValueEx(duk_context *ctx, duk_idx_t i, char* propertyName, char* defaultValue, duk_size_t *len);
#define Duktape_GetStringPropertyValue(ctx, i, propertyName, defaultValue) Duktape_GetStringPropertyValueEx(ctx, i, propertyName, defaultValue, NULL)
int Duktape_GetIntPropertyValue(duk_context *ctx, duk_idx_t i, char* propertyName, int defaultValue);
void *Duktape_GetPointerProperty(duk_context *ctx, duk_idx_t i, char* propertyName);
void *Duktape_GetHeapptrProperty(duk_context *ctx, duk_idx_t i, char* propertyName);
int Duktape_GetBooleanProperty(duk_context *ctx, duk_idx_t i, char *propertyName, int defaultValue);
struct sockaddr_in6* Duktape_IPAddress4_FromString(char* address, unsigned short port);
struct sockaddr_in6* Duktape_IPAddress6_FromString(char* address, unsigned short port);
void ILibDuktape_SockAddrToOptions(duk_context *ctx, struct sockaddr_in6 *addr);
void *ILibDuktape_GetProcessObject(duk_context *ctx);
typedef void(*ILibDuktape_NativeUncaughtExceptionHandler)(duk_context *ctx, char *msg, void *user);
void ILibDuktape_SetNativeUncaughtExceptionHandler(duk_context *ctx, ILibDuktape_NativeUncaughtExceptionHandler handler, void *user);
void ILibDuktape_Process_UncaughtException(duk_context *ctx);
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);
void ILibDuktape_CreateEventWithGetterEx(duk_context *ctx, char *propName, void *heapptr);
void ILibDuktape_CreateEventWithSetter(duk_context *ctx, char *propName, char *propNamePtr, void **hptr);
void ILibDuktape_CreateEventWithSetterEx(duk_context *ctx, char *propName, duk_c_function setterMethod);
void ILibDuktape_CreateEventWithGetterAndSetter(duk_context *ctx, char *propName, char *propNamePtr, void **hptr, duk_c_function getterMethod);
void ILibDuktape_CreateEventWithGetterAndSetterEx(duk_context *ctx, char *propName, duk_c_function getterMethod, duk_c_function setterMethod);
void ILibDuktape_CreateEventWithGetterAndSetterWithMetaData(duk_context *ctx, char* metaDataPropName, duk_idx_t metaDataPropIndex, char *propName, duk_c_function getterMethod, duk_c_function setterMethod);
#define ILibDuktape_CreateEventWithGetterAndSetterWithIntMetaData(context, metaDataPropName, metaDataIntValue, propName, getterMethod, setterMethod) duk_push_int(context, metaDataIntValue);ILibDuktape_CreateEventWithGetterAndSetterWithMetaData(context, metaDataPropName, -1, propName, getterMethod, setterMethod);
#define ILibDuktape_CreateInstanceMethod(context, methodName, funcImpl, numArgs) duk_push_c_function(context, funcImpl, numArgs); duk_put_prop_string(context, -2, methodName)
#define ILibDuktape_CreateInstanceMethodWithPropertyEx(context, propName, propIndex, methodName, funcImpl, numArgs) duk_dup(context, propIndex);if(propIndex<0){duk_remove(context, propIndex - 1);};duk_push_c_function(context, funcImpl, numArgs);duk_swap_top(context, -2);duk_put_prop_string(context, -2, propName);duk_put_prop_string(context, -2, methodName);
#define ILibDuktape_CreateInstanceMethodWithStringProperty(context, propName, propValue, methodName, funcImpl, numArgs) duk_push_string(context, propValue);ILibDuktape_CreateInstanceMethodWithPropertyEx(context, propName, -1, methodName, funcImpl, numArgs);
#define ILibDuktape_CreateInstanceMethodWithBooleanProperty(context, propName, propValue, methodName, funcImpl, numArgs) duk_push_c_function(context, funcImpl, numArgs);duk_push_boolean(context, propValue);duk_put_prop_string(ctx, -2, propName);duk_put_prop_string(ctx, -2, methodName);
#define ILibDuktape_CreateInstanceMethodWithIntProperty(context, propName, propValue, methodName, funcImpl, numArgs) duk_push_c_function(context, funcImpl, numArgs);duk_push_int(context, propValue);duk_put_prop_string(ctx, -2, propName);duk_put_prop_string(ctx, -2, methodName);
#define ILibDuktape_CreateInstanceMethodWithNumberProperty(context, propName, propValue, methodName, funcImpl, numArgs) duk_push_c_function(context, funcImpl, numArgs);duk_push_number(context, (propValue));duk_put_prop_string(ctx, -2, propName);duk_put_prop_string(ctx, -2, methodName);
void ILibDuktape_CreateProperty_InstanceMethod(duk_context *ctx, char *methodName, duk_c_function impl, duk_idx_t argCount);
void ILibDuktape_CreateProperty_InstanceMethodEx(duk_context *ctx, char *methodName, void *funcHeapPtr);
void ILibDuktape_CreateReadonlyProperty(duk_context *ctx, char *propName);
#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_Memory_Alloc(duk_context *ctx, duk_size_t size);
void ILibDuktape_Helper_AddHeapFinalizer(duk_context *ctx, ILibDuktape_HelperEvent handler, void *user);
#endif

View File

@@ -0,0 +1,123 @@
#include "duktape.h"
#include "ILibDuktapeModSearch.h"
#include "ILibDuktape_Helpers.h"
#include "ILibDuktape_DuplexStream.h"
#include "../microstack/ILibParsers.h"
#define ILibDuktape_MemoryStream_Internal "\xFF_MemoryStream_Internal"
#ifdef __DOXY__
/*!
\implements DuplexStream
\brief Buffer Accumulator object, sort of like StringBuilder, etc. <b>Note:</b> To use, must <b>require('MemoryStream')</b> and then <b>new</b> it.
*
* To utilize MemoryStream, you must require('MemoryStream')
*/
class MemoryStream
{
public:
/*!
\brief Returns a new MemoryStream object
*
MemoryStream([initialSize]);
\param initialSize <integer> Optional parameter specifying the initial size of the internal buffer. Default size is 4096 bytes.
*/
MemoryStream([initialSize]);
/*! property buffer
\brief Property returning the accumulated byte[] buffer object
*/
Buffer buffer;
};
#endif
typedef struct ILibDuktape_MemoryStream
{
duk_context *ctx;
size_t initial;
ILibDuktape_DuplexStream *s;
char *buffer;
size_t bufferLen;
size_t bufferSize;
}ILibDuktape_MemoryStream;
ILibTransport_DoneState ILibDuktape_MemoryStream_OnWrite(struct ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user)
{
ILibDuktape_MemoryStream *ms = (ILibDuktape_MemoryStream*)user;
if (ms->bufferSize - ms->bufferLen < (size_t)bufferLen)
{
if ((size_t)bufferLen > ms->bufferSize)
{
if ((ms->buffer = (char*)realloc(ms->buffer, ms->bufferSize + bufferLen)) == NULL) { ILIBCRITICALEXITMSG(254, "OUT OF MEMORY"); }
ms->bufferSize += bufferLen;
}
else
{
if((ms->buffer = (char*)realloc(ms->buffer, 2*ms->bufferSize)) == NULL) { ILIBCRITICALEXITMSG(254, "OUT OF MEMORY"); }
ms->bufferSize = (2 * ms->bufferSize);
}
}
memcpy_s(ms->buffer + ms->bufferLen, ms->bufferSize - ms->bufferLen, buffer, bufferLen);
ms->bufferLen += bufferLen;
return(ILibTransport_DoneState_COMPLETE);
}
void ILibDuktape_MemoryStream_OnEnd(struct ILibDuktape_DuplexStream *stream, void *user)
{
ILibDuktape_MemoryStream *ms = (ILibDuktape_MemoryStream*)user;
ILibDuktape_DuplexStream_WriteEnd(ms->s);
}
duk_ret_t ILibDuktape_MemoryStream_buffer(duk_context *ctx)
{
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, ILibDuktape_MemoryStream_Internal);
ILibDuktape_MemoryStream *ms = (ILibDuktape_MemoryStream*)Duktape_GetBuffer(ctx, -1, NULL);
duk_push_external_buffer(ctx);
duk_config_buffer(ctx, -1, ms->buffer, ms->bufferLen);
return(1);
}
duk_ret_t ILibDuktape_MemoryStream_Finalizer(duk_context *ctx)
{
duk_get_prop_string(ctx, 0, ILibDuktape_MemoryStream_Internal);
ILibDuktape_MemoryStream *ms = (ILibDuktape_MemoryStream*)Duktape_GetBuffer(ctx, -1, NULL);
free(ms->buffer);
return(0);
}
duk_ret_t ILibDuktape_MemoryStream_new(duk_context *ctx)
{
int initial = duk_get_top(ctx) > 0 ? duk_require_int(ctx, 0) : 4096;
ILibDuktape_MemoryStream *ms;
duk_push_object(ctx); // [ms]
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_MemoryStream)); // [ms][internal]
ms = (ILibDuktape_MemoryStream*)Duktape_GetBuffer(ctx, -1, NULL);
memset(ms, 0, sizeof(ILibDuktape_MemoryStream));
duk_put_prop_string(ctx, -2, ILibDuktape_MemoryStream_Internal); // [ms]
ms->buffer = (char*)ILibMemory_Allocate(initial, 0, NULL, NULL);
ms->bufferSize = (size_t)initial;
ms->ctx = ctx;
ms->s = ILibDuktape_DuplexStream_Init(ctx, ILibDuktape_MemoryStream_OnWrite, ILibDuktape_MemoryStream_OnEnd, NULL, NULL, ms);
ILibDuktape_CreateEventWithGetter(ctx, "buffer", ILibDuktape_MemoryStream_buffer);
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_MemoryStream_Finalizer);
return(1);
}
void ILibDuktape_MemoryStream_PUSH(duk_context *ctx, void *chain)
{
duk_push_c_function(ctx, ILibDuktape_MemoryStream_new, DUK_VARARGS);
}
void ILibDuktape_MemoryStream_Init(duk_context *ctx)
{
ILibDuktape_ModSearch_AddHandler(ctx, "MemoryStream", ILibDuktape_MemoryStream_PUSH);
}

View File

@@ -0,0 +1,146 @@
#include "duktape.h"
#include "ILibDuktapeModSearch.h"
#include "ILibDuktape_EventEmitter.h"
#include "ILibDuktape_Helpers.h"
#include "../microstack/ILibParsers.h"
#include "../microstack/ILibIPAddressMonitor.h"
#define ILibDuktape_NetworkMonitor_PTR "\xFF_ILibDuktape_NetworkMonitor"
typedef struct ILibDuktape_NetworkMonitor
{
duk_context *ctx;
ILibDuktape_EventEmitter *emitter;
ILibIPAddressMonitor addressMonitor;
ILibHashtable *addressTable;
void *OnChange;
void *OnAdded;
void *OnRemoved;
}ILibDuktape_NetworkMonitor;
ILibHashtable ILibDuktape_NetworkMonitor_CreateTable(duk_context *ctx)
{
int i;
duk_size_t bufferLen;
char *buffer;
ILibHashtable retVal = NULL;
if (duk_peval_string(ctx, "require('os').networkInterfaces();") != 0)
{
ILibDuktape_Process_UncaughtExceptionEx(ctx, "NetworkMonitor: ");
duk_pop(ctx);
}
else
{ // [networkInterfaces]
retVal = ILibHashtable_Create();
duk_enum(ctx, -1, DUK_ENUM_OWN_PROPERTIES_ONLY); // [networkInterfaces][enum]
while (duk_next(ctx, -1, 1))
{
// [networkInterfaces][enum][adapter][array]
int count = duk_get_length(ctx, -1);
for (i = 0; i < count; ++i)
{
duk_get_prop_index(ctx, -1, i); // [networkInterfaces][enum][adapter][array][obj]
if (duk_has_prop_string(ctx, -1, "address") && strcmp(Duktape_GetStringPropertyValue(ctx, -1, "status", "up"), "up") == 0)
{
duk_get_prop_string(ctx, -1, "address");// [networkInterfaces][enum][adapter][array][obj][address]
buffer = (char*)duk_get_lstring(ctx, -1, &bufferLen);
ILibHashtable_Put(retVal, NULL, buffer, bufferLen, (void*)0x01);
duk_pop(ctx); // [networkInterfaces][enum][adapter][array][obj]
}
duk_pop(ctx); // [networkInterfaces][enum][adapter][array]
}
duk_pop_2(ctx); // [networkInterfaces][enum]
}
duk_pop_2(ctx); // ...
}
return(retVal);
}
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];
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);
}
}
}
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); // ...
}
ILibHashtable current = ILibDuktape_NetworkMonitor_CreateTable(nm->ctx);
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;
}
duk_ret_t ILibDuktape_NetworkMonitor_Finalizer(duk_context *ctx)
{
if (ILibIsChainBeingDestroyed(Duktape_GetChain(ctx)) != 0) { return(0); }
duk_get_prop_string(ctx, 0, ILibDuktape_NetworkMonitor_PTR);
ILibDuktape_NetworkMonitor *nm = (ILibDuktape_NetworkMonitor*)Duktape_GetBuffer(ctx, -1, NULL);
ILibChain_SafeRemoveEx(Duktape_GetChain(ctx), nm->addressMonitor);
if (nm->addressTable != NULL) { ILibHashtable_Destroy(nm->addressTable); }
return(0);
}
void ILibDuktape_NetworkMonitor_PUSH(duk_context *ctx, void *chain)
{
duk_push_object(ctx);
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_NetworkMonitor));
ILibDuktape_NetworkMonitor *nm = (ILibDuktape_NetworkMonitor*)Duktape_GetBuffer(ctx, -1, NULL);
memset(nm, 0, sizeof(ILibDuktape_NetworkMonitor));
duk_put_prop_string(ctx, -2, ILibDuktape_NetworkMonitor_PTR);
nm->ctx = ctx;
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_CreateFinalizer(ctx, ILibDuktape_NetworkMonitor_Finalizer);
//
// Get initial list of addresses
//
nm->addressTable = ILibDuktape_NetworkMonitor_CreateTable(ctx);
}
void ILibDuktape_NetworkMonitor_Init(duk_context *ctx)
{
ILibDuktape_ModSearch_AddHandler(ctx, "NetworkMonitor", ILibDuktape_NetworkMonitor_PUSH);
}

View File

@@ -0,0 +1,32 @@
#ifndef __ILIBDUKTAPE_NETWORKMONITOR__
#define __ILIBDUKTAPE_NETWORKMONITOR__
#include "duktape.h"
#ifdef __DOXY__
/*!
\brief NetworkMonitor emits events whenever the status of one of the network interfaces changes. <b>Note:</b> To use, must <b>require('NetworkMonitor')</b>
*/
class NetworkMonitor
{
public:
/*!
\brief 'change' event is emitted whenever any of the interfaces changes state
*/
void change;
/*!
\brief 'add' event is emitted when a new IPAddress is assigned to one of the network interfaces
\param addr The IPAddress that was added or assigned
*/
void add;
/*!
\brief 'remove' event is emitted when an IPAddress is removed from one of the network interfaces
\param addr The IPAddress that was removed.
*/
void remove;
};
#endif
void ILibDuktape_NetworkMonitor_Init(duk_context *ctx);
#endif

View File

@@ -0,0 +1,604 @@
#include "duktape.h"
#include "ILibDuktape_Helpers.h"
#include "ILibDuktapeModSearch.h"
#include "../microstack/ILibParsers.h"
#include "../microstack/ILibCrypto.h"
#define ILibDuktape_Timer_Ptrs "\xFF_DuktapeTimer_PTRS"
duk_ret_t ILibDuktape_Pollyfills_Buffer_slice(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
char *buffer;
char *out;
duk_size_t bufferLen;
int offset = 0;
duk_push_this(ctx);
buffer = Duktape_GetBuffer(ctx, -1, &bufferLen);
if (nargs >= 1)
{
offset = duk_require_int(ctx, 0);
bufferLen -= offset;
}
if (nargs == 2)
{
bufferLen = (duk_size_t)duk_require_int(ctx, 1) - offset;
}
duk_push_fixed_buffer(ctx, bufferLen);
out = Duktape_GetBuffer(ctx, -1, NULL);
memcpy_s(out, bufferLen, buffer + offset, bufferLen);
return 1;
}
duk_ret_t ILibDuktape_Polyfills_Buffer_toString(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
char *buffer, *tmpBuffer;
duk_size_t bufferLen;
char *cType;
duk_push_this(ctx); // [buffer]
buffer = Duktape_GetBuffer(ctx, -1, &bufferLen);
if (nargs == 0)
{
// Just convert to a string
duk_push_lstring(ctx, buffer, bufferLen); // [buffer][string]
}
else
{
cType = (char*)duk_require_string(ctx, 0);
if (strcmp(cType, "base64") == 0)
{
duk_push_fixed_buffer(ctx, ILibBase64EncodeLength((int)bufferLen));
tmpBuffer = Duktape_GetBuffer(ctx, -1, NULL);
ILibBase64Encode((unsigned char*)buffer, (int)bufferLen, (unsigned char**)&tmpBuffer);
duk_push_string(ctx, tmpBuffer);
}
else if (strcmp(cType, "hex") == 0)
{
duk_push_fixed_buffer(ctx, 1 + (bufferLen * 2));
tmpBuffer = Duktape_GetBuffer(ctx, -1, NULL);
util_tohex(buffer, (int)bufferLen, tmpBuffer);
duk_push_string(ctx, tmpBuffer);
}
else
{
duk_push_string(ctx, "buffer.toString(): Unrecognized parameter");
duk_throw(ctx);
return(DUK_RET_ERROR);
}
}
return 1;
}
duk_ret_t ILibDuktape_Polyfills_Buffer_from(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
char *str;
duk_size_t strlength;
char *encoding;
char *buffer;
int bufferLen;
if (!(nargs == 2 && duk_is_string(ctx, 0) && duk_is_string(ctx, 1)))
{
duk_push_string(ctx, "Buffer.from(): Usage not supported yet.");
duk_throw(ctx);
return(DUK_RET_ERROR);
}
str = (char*)duk_get_lstring(ctx, 0, &strlength);
encoding = (char*)duk_require_string(ctx, 1);
if (strcmp(encoding, "base64") == 0)
{
// Base64
duk_push_fixed_buffer(ctx, ILibBase64DecodeLength((int)strlength));
buffer = Duktape_GetBuffer(ctx, -1, NULL);
bufferLen = ILibBase64Decode((unsigned char*)str, (int)strlength, (unsigned char**)&buffer);
duk_push_buffer_object(ctx, -1, 0, bufferLen, DUK_BUFOBJ_DUKTAPE_BUFFER);
}
else if (strcmp(encoding, "hex") == 0)
{
duk_push_fixed_buffer(ctx, strlength / 2);
buffer = Duktape_GetBuffer(ctx, -1, NULL);
bufferLen = util_hexToBuf(str, (int)strlength, buffer);
duk_push_buffer_object(ctx, -1, 0, bufferLen, DUK_BUFOBJ_DUKTAPE_BUFFER);
}
else
{
duk_push_string(ctx, "Buffer.from(): Encoding not supported yet.");
duk_throw(ctx);
return(DUK_RET_ERROR);
}
return 1;
}
void ILibDuktape_Polyfills_Buffer(duk_context *ctx)
{
// Polyfill 'Buffer.slice'
duk_get_prop_string(ctx, -1, "Duktape"); // [g][Duktape]
duk_get_prop_string(ctx, -1, "Buffer"); // [g][Duktape][Buffer]
duk_get_prop_string(ctx, -1, "prototype"); // [g][Duktape][Buffer][prototype]
duk_push_c_function(ctx, ILibDuktape_Pollyfills_Buffer_slice, DUK_VARARGS); // [g][Duktape][Buffer][prototype][func]
duk_put_prop_string(ctx, -2, "slice"); // [g][Duktape][Buffer][prototype]
duk_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]
duk_push_c_function(ctx, ILibDuktape_Polyfills_Buffer_from, DUK_VARARGS); // [g][Buffer][func]
duk_put_prop_string(ctx, -2, "from"); // [g][Buffer]
duk_pop(ctx);
}
duk_ret_t ILibDuktape_Polyfills_String_startsWith(duk_context *ctx)
{
duk_size_t tokenLen;
char *token = Duktape_GetBuffer(ctx, 0, &tokenLen);
char *buffer;
duk_size_t bufferLen;
duk_push_this(ctx);
buffer = Duktape_GetBuffer(ctx, -1, &bufferLen);
if (ILibString_StartsWith(buffer, (int)bufferLen, token, (int)tokenLen) != 0)
{
duk_push_true(ctx);
}
else
{
duk_push_false(ctx);
}
return 1;
}
void ILibDuktape_Polyfills_String(duk_context *ctx)
{
// Polyfill 'String.startsWith'
duk_get_prop_string(ctx, -1, "String"); // [string]
duk_get_prop_string(ctx, -1, "prototype"); // [string][proto]
duk_push_c_function(ctx, ILibDuktape_Polyfills_String_startsWith, DUK_VARARGS); // [string][proto][func]
duk_put_prop_string(ctx, -2, "startsWith"); // [string][proto]
duk_pop_2(ctx);
}
duk_ret_t ILibDuktape_Polyfills_Console_log(duk_context *ctx)
{
int numargs = duk_get_top(ctx);
int i;
for (i = 0; i < numargs; ++i)
{
if (duk_is_string(ctx, i))
{
printf("%s%s", (i == 0 ? "" : ", "), duk_require_string(ctx, i));
}
else
{
duk_dup(ctx, i);
printf("%s%s", (i == 0 ? "" : ", "), duk_to_string(ctx, -1));
}
}
printf("\n");
return 0;
}
void ILibDuktape_Polyfills_Console(duk_context *ctx)
{
// Polyfill console.log()
if (duk_has_prop_string(ctx, -1, "console"))
{
duk_get_prop_string(ctx, -1, "console"); // [g][console]
}
else
{
duk_push_object(ctx); // [g][console]
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]
duk_pop(ctx); // [g]
}
duk_ret_t ILibDuktape_ntohl(duk_context *ctx)
{
duk_size_t bufferLen;
char *buffer = Duktape_GetBuffer(ctx, 0, &bufferLen);
int offset = duk_require_int(ctx, 1);
if ((int)bufferLen < (4 + offset)) { duk_push_string(ctx, "buffer too small"); duk_throw(ctx); return(DUK_RET_ERROR); }
duk_push_int(ctx, ntohl(((unsigned int*)(buffer + offset))[0]));
return 1;
}
duk_ret_t ILibDuktape_ntohs(duk_context *ctx)
{
duk_size_t bufferLen;
char *buffer = Duktape_GetBuffer(ctx, 0, &bufferLen);
int offset = duk_require_int(ctx, 1);
if ((int)bufferLen < 2 + offset) { duk_push_string(ctx, "buffer too small"); duk_throw(ctx); return(DUK_RET_ERROR); }
duk_push_int(ctx, ntohs(((unsigned short*)(buffer + offset))[0]));
return 1;
}
duk_ret_t ILibDuktape_htonl(duk_context *ctx)
{
duk_size_t bufferLen;
char *buffer = Duktape_GetBuffer(ctx, 0, &bufferLen);
int offset = duk_require_int(ctx, 1);
unsigned int val = (unsigned int)duk_require_int(ctx, 2);
if ((int)bufferLen < (4 + offset)) { duk_push_string(ctx, "buffer too small"); duk_throw(ctx); return(DUK_RET_ERROR); }
((unsigned int*)(buffer + offset))[0] = htonl(val);
return 0;
}
duk_ret_t ILibDuktape_htons(duk_context *ctx)
{
duk_size_t bufferLen;
char *buffer = Duktape_GetBuffer(ctx, 0, &bufferLen);
int offset = duk_require_int(ctx, 1);
unsigned int val = (unsigned int)duk_require_int(ctx, 2);
if ((int)bufferLen < (2 + offset)) { duk_push_string(ctx, "buffer too small"); duk_throw(ctx); return(DUK_RET_ERROR); }
((unsigned short*)(buffer + offset))[0] = htons(val);
return 0;
}
void ILibDuktape_Polyfills_byte_ordering(duk_context *ctx)
{
ILibDuktape_CreateInstanceMethod(ctx, "ntohl", ILibDuktape_ntohl, 2);
ILibDuktape_CreateInstanceMethod(ctx, "ntohs", ILibDuktape_ntohs, 2);
ILibDuktape_CreateInstanceMethod(ctx, "htonl", ILibDuktape_htonl, 3);
ILibDuktape_CreateInstanceMethod(ctx, "htons", ILibDuktape_htons, 3);
}
typedef enum ILibDuktape_Timer_Type
{
ILibDuktape_Timer_Type_TIMEOUT = 0,
ILibDuktape_Timer_Type_INTERVAL = 1,
ILibDuktape_Timer_Type_IMMEDIATE = 2
}ILibDuktape_Timer_Type;
typedef struct ILibDuktape_Timer
{
duk_context *ctx;
void *object;
void *callback;
void *args;
int timeout;
ILibDuktape_Timer_Type timerType;
}ILibDuktape_Timer;
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);
ptrs = (ILibDuktape_Timer*)Duktape_GetBuffer(ctx, -1, NULL);
ILibLifeTime_Remove(ILibGetBaseTimer(Duktape_GetChain(ctx)), ptrs);
return 0;
}
void ILibDuktape_Polyfills_timer_elapsed(void *obj)
{
ILibDuktape_Timer *ptrs = (ILibDuktape_Timer*)obj;
int argCount, i;
if (ptrs->timerType == ILibDuktape_Timer_Type_INTERVAL)
{
ILibLifeTime_AddEx(ILibGetBaseTimer(Duktape_GetChain(ptrs->ctx)), ptrs, ptrs->timeout, ILibDuktape_Polyfills_timer_elapsed, NULL);
}
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);
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_pop(ptrs->ctx); // [func][this][...arg...]
if (duk_pcall_method(ptrs->ctx, argCount) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ptrs->ctx, "timers.onElapsed() callback handler"); }
duk_pop(ptrs->ctx); // ...
}
duk_ret_t ILibDuktape_Polyfills_timer_set(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
ILibDuktape_Timer *ptrs;
ILibDuktape_Timer_Type timerType;
void *chain = Duktape_GetChain(ctx);
int argx;
duk_push_current_function(ctx);
duk_get_prop_string(ctx, -1, "type");
timerType = (ILibDuktape_Timer_Type)duk_get_int(ctx, -1);
duk_push_object(ctx); //[retVal]
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);
memset(ptrs, 0, sizeof(ILibDuktape_Timer));
duk_put_prop_string(ctx, -2, ILibDuktape_Timer_Ptrs); //[retVal]
ptrs->ctx = ctx;
ptrs->object = duk_get_heapptr(ctx, -1);
ptrs->timerType = timerType;
ptrs->timeout = timerType == ILibDuktape_Timer_Type_IMMEDIATE ? 0 : (int)duk_require_int(ctx, 1);
ptrs->callback = duk_require_heapptr(ctx, 0);
duk_push_array(ctx); //[retVal][argArray]
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]
}
ptrs->args = duk_get_heapptr(ctx, -1);
duk_put_prop_string(ctx, -2, "\xFF_argArray");
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;
}
duk_ret_t ILibDuktape_Polyfills_timer_clear(duk_context *ctx)
{
ILibDuktape_Timer *ptrs;
ILibDuktape_Timer_Type timerType;
duk_push_current_function(ctx);
duk_get_prop_string(ctx, -1, "type");
timerType = (ILibDuktape_Timer_Type)duk_get_int(ctx, -1);
if(!duk_has_prop_string(ctx, 0, ILibDuktape_Timer_Ptrs))
{
switch (timerType)
{
case ILibDuktape_Timer_Type_TIMEOUT:
return(ILibDuktape_Error(ctx, "timers.clearTimeout(): Invalid Parameter"));
case ILibDuktape_Timer_Type_INTERVAL:
return(ILibDuktape_Error(ctx, "timers.clearInterval(): Invalid Parameter"));
case ILibDuktape_Timer_Type_IMMEDIATE:
return(ILibDuktape_Error(ctx, "timers.clearImmediate(): Invalid Parameter"));
}
}
duk_get_prop_string(ctx, 0, ILibDuktape_Timer_Ptrs);
ptrs = (ILibDuktape_Timer*)Duktape_GetBuffer(ctx, -1, NULL);
ILibLifeTime_Remove(ILibGetBaseTimer(Duktape_GetChain(ctx)), ptrs);
return 0;
}
void ILibDuktape_Polyfills_timer(duk_context *ctx)
{
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "type", ILibDuktape_Timer_Type_TIMEOUT, "setTimeout", ILibDuktape_Polyfills_timer_set, DUK_VARARGS);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "type", ILibDuktape_Timer_Type_INTERVAL, "setInterval", ILibDuktape_Polyfills_timer_set, DUK_VARARGS);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "type", ILibDuktape_Timer_Type_IMMEDIATE, "setImmediate", ILibDuktape_Polyfills_timer_set, DUK_VARARGS);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "type", ILibDuktape_Timer_Type_TIMEOUT, "clearTimeout", ILibDuktape_Polyfills_timer_clear, 1);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "type", ILibDuktape_Timer_Type_INTERVAL, "clearInterval", ILibDuktape_Polyfills_timer_clear, 1);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "type", ILibDuktape_Timer_Type_IMMEDIATE, "clearImmediate", ILibDuktape_Polyfills_timer_clear, 1);
}
duk_ret_t ILibDuktape_Polyfills_addModule(duk_context *ctx)
{
duk_size_t moduleLen;
char *module = (char*)Duktape_GetBuffer(ctx, 1, &moduleLen);
char *moduleName = (char*)duk_require_string(ctx, 0);
if (ILibDuktape_ModSearch_AddModule(ctx, moduleName, module, moduleLen) != 0)
{
return(ILibDuktape_Error(ctx, "Cannot add module: %s", moduleName));
}
return(0);
}
void ILibDuktape_Polyfills_Init(duk_context *ctx)
{
// Global Polyfills
duk_push_global_object(ctx); // [g]
ILibDuktape_Polyfills_String(ctx);
ILibDuktape_Polyfills_Buffer(ctx);
ILibDuktape_Polyfills_Console(ctx);
ILibDuktape_Polyfills_byte_ordering(ctx);
ILibDuktape_Polyfills_timer(ctx);
ILibDuktape_CreateInstanceMethod(ctx, "addModule", ILibDuktape_Polyfills_addModule, 2);
duk_pop(ctx); // ...
}
#ifdef __DOXY__
/*!
\brief String
*/
class String
{
public:
/*!
\brief Finds a String within another String
\param str \<String\> Substring to search for
\return <Integer> Index of where the string was found. -1 if not found
*/
Integer indexOf(str);
/*!
\brief Extracts a String from a String.
\param startIndex <Integer> Starting index to extract
\param length <Integer> Number of characters to extract
\return \<String\> extracted String
*/
String substr(startIndex, length);
/*!
\brief Extracts a String from a String.
\param startIndex <Integer> Starting index to extract
\param endIndex <Integer> Ending index to extract
\return \<String\> extracted String
*/
String splice(startIndex, endIndex);
/*!
\brief Split String into substrings
\param str \<String\> Delimiter to split on
\return Array of Tokens
*/
Array<String> split(str);
/*!
\brief Determines if a String starts with the given substring
\param str \<String\> substring
\return <boolean> True, if this String starts with the given substring
*/
boolean startsWith(str);
};
/*!
\brief Instances of the Buffer class are similar to arrays of integers but correspond to fixed-sized, raw memory allocations.
*/
class Buffer
{
public:
/*!
\brief Create a new Buffer instance of the specified number of bytes
\param size <integer>
\return \<Buffer\> new Buffer instance
*/
Buffer(size);
/*!
\brief Returns the amount of memory allocated in bytes
*/
integer length;
/*!
\brief Creates a new Buffer instance from an encoded String
\param str \<String\> encoded String
\param encoding \<String\> Encoding. Can be either 'base64' or 'hex'
\return \<Buffer\> new Buffer instance
*/
static Buffer from(str, encoding);
/*!
\brief Decodes Buffer to a String
\param encoding \<String\> Optional. Can be either 'base64' or 'hex'. If not specified, will just encode as an ANSI string
\param start <integer> Optional. Starting offset. <b>Default:</b> 0
\param end <integer> Optional. Ending offset (not inclusive) <b>Default:</b> buffer length
\return \<String\> Encoded String
*/
String toString([encoding[, start[, end]]]);
/*!
\brief Returns a new Buffer that references the same memory as the original, but offset and cropped by the start and end indices.
\param start <integer> Where the new Buffer will start. <b>Default:</b> 0
\param end <integer> Where the new Buffer will end. (Not inclusive) <b>Default:</b> buffer length
\return \<Buffer\>
*/
Buffer slice([start[, end]]);
};
/*!
\brief Console
*/
class Console
{
public:
/*!
\brief Serializes the input parameters to the Console Display
\param args <any>
*/
void log(...args);
};
/*!
\brief Global Timer Methods
*/
class Timers
{
public:
/*!
\brief Schedules the "immediate" execution of the callback after I/O events' callbacks.
\param callback <func> Function to call at the end of the event loop
\param args <any> Optional arguments to pass when the callback is called
\return Immediate for use with clearImmediate().
*/
Immediate setImmediate(callback[, ...args]);
/*!
\brief Schedules execution of a one-time callback after delay milliseconds.
\param callback <func> Function to call when the timeout elapses
\param args <any> Optional arguments to pass when the callback is called
\return Timeout for use with clearTimeout().
*/
Timeout setTimeout(callback, delay[, ...args]);
/*!
\brief Schedules repeated execution of callback every delay milliseconds.
\param callback <func> Function to call when the timer elapses
\param args <any> Optional arguments to pass when the callback is called
\return Timeout for use with clearInterval().
*/
Timeout setInterval(callback, delay[, ...args]);
/*!
\brief Cancels a Timeout returned by setTimeout()
\param timeout Timeout
*/
void clearTimeout(timeout);
/*!
\brief Cancels a Timeout returned by setInterval()
\param interval Timeout
*/
void clearInterval(interval);
/*!
\brief Cancels an Immediate returned by setImmediate()
\param immediate Immediate
*/
void clearImmediate(immediate);
/*!
\brief Scheduled Timer
*/
class Timeout
{
public:
};
/*!
\implements Timeout
\brief Scheduled Immediate
*/
class Immediate
{
public:
};
};
/*!
\brief Global methods for byte ordering manipulation
*/
class BytesOrdering
{
public:
/*!
\brief Converts 2 bytes from network order to host order
\param buffer \<Buffer\> bytes to convert
\param offset <integer> offset to start
\return <integer> host order value
*/
static integer ntohs(buffer, offset);
/*!
\brief Converts 4 bytes from network order to host order
\param buffer \<Buffer\> bytes to convert
\param offset <integer> offset to start
\return <integer> host order value
*/
static integer ntohl(buffer, offset);
/*!
\brief Writes 2 bytes in network order
\param buffer \<Buffer\> Buffer to write to
\param offset <integer> offset to start writing
\param val <integer> host order value to write
*/
static void htons(buffer, offset, val);
/*!
\brief Writes 4 bytes in network order
\param buffer \<Buffer\> Buffer to write to
\param offset <integer> offset to start writing
\param val <integer> host order value to write
*/
static void htonl(buffer, offset, val);
};
#endif

View File

@@ -0,0 +1,8 @@
#ifndef __ILibDuktape_Polyfills__
#define __ILibDuktape_Polyfills__
#include "duktape.h"
void ILibDuktape_Polyfills_Init(duk_context *ctx);
#endif

View File

@@ -0,0 +1,256 @@
#include "duktape.h"
#if defined(WINSOCK2)
#include <winsock2.h>
#include <ws2tcpip.h>
#endif
#include "microstack/ILibParsers.h"
#include "microstack/ILibProcessPipe.h"
#include "ILibDuktape_ProcessPipe.h"
#include "ILibDuktape_Helpers.h"
#include "ILibDuktape_DuplexStream.h"
#include "ILibDuktapeModSearch.h"
#define ILibDuktape_ProcessPipe_Process_ErrorStreamPtr "\xFF_ErrorStreamPtr"
#define ILibDuktape_ProcessPipe_Process_ErrorStreamPtrNative "\xFF_ErrorStreamPtrNative"
#define ILibDuktape_ProcessPipe_Process_PTR "\xFFProcessPtr"
ILibTransport_DoneState ILibDuktape_ProcessPipe_Process_JSOnWrite(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user)
{
// Called when JavaScript has written bytes to this object
ILibProcessPipe_Process mProcess = (ILibProcessPipe_Process)user;
return(ILibProcessPipe_Process_WriteStdIn(mProcess, buffer, bufferLen, ILibTransport_MemoryOwnership_USER));
}
void ILibDuktape_ProcessPipe_Process_JSOnEnd(ILibDuktape_DuplexStream *stream, void *user)
{
// Called when JavaScript has specified that it will no longer write data
ILibProcessPipe_Process mProcess = (ILibProcessPipe_Process)user;
if (mProcess != NULL)
{
ILibProcessPipe_Process_KillEx(mProcess);
duk_push_heapptr(stream->readableStream->ctx, stream->ParentObject); // [process]
duk_del_prop_string(stream->readableStream->ctx, -1, ILibDuktape_ProcessPipe_Process_PTR);
duk_pop(stream->readableStream->ctx);
ILibProcessPipe_Process_UpdateUserObject(mProcess, NULL);
stream->user = NULL;
}
}
void ILibDuktape_ProcessPipe_Process_JSPause(ILibDuktape_DuplexStream *sender, void *user)
{
// Called when either JavaScript called Pause, or JavaScript has not attached a reader yet
ILibProcessPipe_Process mProcess = (ILibProcessPipe_Process)user;
ILibProcessPipe_Pipe_Pause(ILibProcessPipe_Process_GetStdOut(mProcess));
}
void ILibDuktape_ProcessPipe_Process_JSResume(ILibDuktape_DuplexStream *sender, void *user)
{
// Called when JavaScript called Resume
ILibProcessPipe_Process mProcess = (ILibProcessPipe_Process)user;
ILibProcessPipe_Pipe_Resume(ILibProcessPipe_Process_GetStdOut(mProcess));
}
void ILibDuktape_ProcessPipe_Process_OnExit(ILibProcessPipe_Process sender, int exitCode, void* user)
{
if (user == NULL) { return; }
// Called when process has exited
ILibDuktape_DuplexStream* stream = (ILibDuktape_DuplexStream*)user;
ILibProcessPipe_Process_UpdateUserObject(sender, NULL);
ILibDuktape_DuplexStream_WriteEnd(stream);
duk_push_heapptr(stream->readableStream->ctx, stream->ParentObject); // [process]
duk_del_prop_string(stream->readableStream->ctx, -1, ILibDuktape_ProcessPipe_Process_PTR);
duk_pop(stream->readableStream->ctx);
}
void ILibDuktape_ProcessPipe_Process_OnStdOut(ILibProcessPipe_Process sender, char *buffer, int bufferLen, int* bytesConsumed, void* user)
{
if (user == NULL) { return; }
// Called when process has written data
ILibDuktape_DuplexStream* ds = (ILibDuktape_DuplexStream*)user;
ILibDuktape_DuplexStream_WriteData(ds, buffer, bufferLen);
*bytesConsumed = bufferLen;
}
void ILibDuktape_ProcessPipe_Process_OnStdErr(ILibProcessPipe_Process sender, char *buffer, int bufferLen, int* bytesConsumed, void* user)
{
if (user == NULL) { return; }
// Called when process has written error data
ILibDuktape_DuplexStream* ds = (ILibDuktape_DuplexStream*)user;
ILibDuktape_readableStream *rs;
duk_push_heapptr(ds->readableStream->ctx, ds->ParentObject); // [process]
duk_get_prop_string(ds->readableStream->ctx, -1, ILibDuktape_ProcessPipe_Process_ErrorStreamPtrNative); // [process][error]
rs = (ILibDuktape_readableStream*)duk_get_pointer(ds->readableStream->ctx, -1);
ILibDuktape_readableStream_WriteData(rs, buffer, bufferLen);
*bytesConsumed = bufferLen;
}
void ILibDuktape_ProcessPipe_Process_OnSendOK(ILibProcessPipe_Process sender, void* user)
{
if (user == NULL) { return; }
//ToDo: Finish this
}
duk_ret_t ILibDuktape_ProcessPipe_Process_Finalizer(duk_context *ctx)
{
ILibProcessPipe_Process mProcess;
duk_dup(ctx, 0);
duk_get_prop_string(ctx, -1, ILibDuktape_ProcessPipe_Process_PTR);
mProcess = (ILibProcessPipe_Process)duk_get_pointer(ctx, -1);
if (mProcess != NULL)
{
ILibProcessPipe_Process_UpdateUserObject(mProcess, NULL);
ILibProcessPipe_Process_KillEx(mProcess);
}
if (duk_has_prop_string(ctx, 0, ILibDuktape_DuplexStream_bufferPtr))
{
duk_get_prop_string(ctx, 0, ILibDuktape_DuplexStream_bufferPtr);
memset(Duktape_GetBuffer(ctx, -1, NULL), 0, sizeof(ILibDuktape_DuplexStream));
}
return 0;
}
void ILibDuktape_ProcessPipe_ErrorStream_Pause(struct ILibDuktape_readableStream *sender, void *user)
{
ILibProcessPipe_Process mProcess = (ILibProcessPipe_Process)user;
ILibProcessPipe_Pipe_Pause(ILibProcessPipe_Process_GetStdErr(mProcess));
}
void ILibDuktape_ProcessPipe_ErrorStream_Resume(struct ILibDuktape_readableStream *sender, void *user)
{
ILibProcessPipe_Process mProcess = (ILibProcessPipe_Process)user;
ILibProcessPipe_Pipe_Resume(ILibProcessPipe_Process_GetStdErr(mProcess));
}
duk_ret_t ILibDuktape_ProcessPipe_ErrorStream_Getter(duk_context *ctx)
{
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, ILibDuktape_ProcessPipe_Process_ErrorStreamPtr);
return 1;
}
duk_ret_t ILibDuktape_ProcessPipe_CreateProcess(duk_context *ctx)
{
ILibProcessPipe_Manager pipeManager;
ILibProcessPipe_Process mProcess;
ILibDuktape_DuplexStream* ds;
ILibDuktape_readableStream *rs;
duk_size_t targetLen;
int nargs = duk_get_top(ctx);
char *target;
char **params = NULL;
int i, x;
ILibProcessPipe_SpawnTypes asUser = ILibProcessPipe_SpawnTypes_DEFAULT;
if (nargs < 1) { duk_push_string(ctx, "ProcessPipe.CreateProcess: Invalid number of args"); duk_throw(ctx); return(DUK_RET_ERROR); }
// Parse Parameters
target = (char*)duk_get_lstring(ctx, 0, &targetLen);
#ifdef WIN32
if (target[0] == '%')
{
size_t evsize;
int pctx = ILibString_IndexOf(target + 1, (int)targetLen - 1, "%", 1);
if (pctx > 0)
{
memcpy_s(ILibScratchPad, sizeof(ILibScratchPad), target + 1, pctx);
ILibScratchPad[pctx] = 0;
getenv_s(&evsize, ILibScratchPad2, sizeof(ILibScratchPad2), ILibScratchPad);
if (evsize > 0)
{
strncpy_s(ILibScratchPad2 + evsize - 1, sizeof(ILibScratchPad2) - evsize, target + pctx + 2, targetLen - pctx - 2);
target = ILibScratchPad2;
}
}
}
#endif
if (nargs > 1)
{
x = 0;
params = (char**)ILibMemory_Allocate((nargs * sizeof(char*)), 0, NULL, NULL);
for (i = 1; i < nargs; ++i)
{
if (duk_is_number(ctx, i))
{
asUser = (ILibProcessPipe_SpawnTypes)duk_require_int(ctx, i);
}
else
{
params[x++] = (char*)duk_require_string(ctx, i);
}
}
params[x] = NULL;
}
duk_push_this(ctx); // [manager]
duk_get_prop_string(ctx, -1, "\xFFPipeManager"); // [manager][pipeManager]
pipeManager = (ILibProcessPipe_Manager)duk_get_pointer(ctx, -1);
mProcess = ILibProcessPipe_Manager_SpawnProcessEx(pipeManager, target, params, asUser);
if (params != NULL) { free(params); }
if (mProcess != NULL)
{
duk_push_object(ctx); // [manager][pipeManager][retVal]
duk_push_pointer(ctx, mProcess); // [manager][pipeManager][retVal][process]
duk_put_prop_string(ctx, -2, ILibDuktape_ProcessPipe_Process_PTR); // [manager][pipeManager][retVal]
ILibDuktape_CreateReadonlyProperty_int(ctx, "pid", ILibProcessPipe_Process_GetPID(mProcess));
ds = ILibDuktape_DuplexStream_Init(ctx, ILibDuktape_ProcessPipe_Process_JSOnWrite,
ILibDuktape_ProcessPipe_Process_JSOnEnd, ILibDuktape_ProcessPipe_Process_JSPause,
ILibDuktape_ProcessPipe_Process_JSResume, mProcess);
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_ProcessPipe_Process_Finalizer);
ILibProcessPipe_Process_AddHandlers(mProcess, 4096, ILibDuktape_ProcessPipe_Process_OnExit,
ILibDuktape_ProcessPipe_Process_OnStdOut, ILibDuktape_ProcessPipe_Process_OnStdErr,
ILibDuktape_ProcessPipe_Process_OnSendOK, ds);
duk_push_object(ctx); // [manager][pipeManager][retVal][error]
ILibDuktape_CreateEventWithGetterEx(ctx, "parent", duk_get_heapptr(ctx, -2));
rs = ILibDuktape_ReadableStream_Init(ctx, ILibDuktape_ProcessPipe_ErrorStream_Pause, ILibDuktape_ProcessPipe_ErrorStream_Resume, mProcess);
duk_put_prop_string(ctx, -2, ILibDuktape_ProcessPipe_Process_ErrorStreamPtr); // [manager][pipeManager][retVal]
ILibDuktape_CreateEventWithGetter(ctx, "error", ILibDuktape_ProcessPipe_ErrorStream_Getter);
duk_push_pointer(ctx, rs); // [manager][pipeManager][retVal][ptr]
duk_put_prop_string(ctx, -2, ILibDuktape_ProcessPipe_Process_ErrorStreamPtrNative); // [manager][pipeManager][retVal]
}
else
{
duk_push_null(ctx);
}
return 1;
}
duk_ret_t ILibDuktape_ProcessPipe_Finalizer(duk_context *ctx)
{
ILibProcessPipe_Manager *pipeManager;
duk_dup(ctx, 0); // [obj]
duk_get_prop_string(ctx, -1, "\xFFPipeManager"); // [obj][manager]
pipeManager = (ILibProcessPipe_Manager)duk_get_pointer(ctx, -1);
ILibChain_SafeRemove(((ILibChain_Link*)pipeManager)->ParentChain, pipeManager);
return 0;
}
void ILibDuktape_ProcessPipe_PUSH(duk_context *ctx, void *chain)
{
ILibProcessPipe_Manager pipeManager = ILibProcessPipe_Manager_Create(chain);
duk_push_object(ctx); // [obj]
duk_push_pointer(ctx, pipeManager); // [obj][pipeManager]
duk_put_prop_string(ctx, -2, "\xFFPipeManager"); // [obj]
ILibDuktape_CreateInstanceMethod(ctx, "CreateProcess", ILibDuktape_ProcessPipe_CreateProcess, DUK_VARARGS);
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_ProcessPipe_Finalizer);
Duktape_CreateEnum(ctx, "ILibProcessPipe_SpawnTypes", (char*[]) { "DEFAULT", "USER", "WINLOGON", "TERM" }, (int[]) { 0, 1, 2, 3 }, 4);
}
void ILibDuktape_ProcessPipe_Init(duk_context * ctx, void * chain)
{
ILibDuktape_ModSearch_AddHandler(ctx, "ILibProcessPipe", ILibDuktape_ProcessPipe_PUSH);
}

View File

@@ -0,0 +1,71 @@
#ifndef __DUKTAPE_PROCESSPIPE__
#define __DUKTAPE_PROCESSPIPE__
#include "duktape.h"
#ifdef __DOXY__
/*!
\brief An object that is used to spawn child processes to perform various tasks. <b>Note:</b> To use, must <b>require('ILibProcessPipe')</b>
*/
class ILibProcessPipe
{
public:
/*!
\brief Spawns a child process
*
ILibProcessPipe_Process CreateProcess(target[, spawnType][, ...args]);
\param target \<String\> The target module to execute
\param spawnType <ILibProcessPipe_SpawnTypes> The optional process type to spawn
\param args \<String\> optional paramaters to pass to target on the command line. The first one is argv0, the second is argv1, etc.
\returns \<ILibProcessPipe_Process\> stream attached to child process. NULL if the process could not be spawned.
*/
ILibProcessPipe_Process CreateProcess(target[, spawnType][, ...args]);
/*!
\brief Specifies the type of child process to spawn
*/
enum class ILibProcessPipe_SpawnTypes
{
DEFAULT, /*!< Same as parent*/
USER, /*!< Currently logged on user*/
WINLOGON, /*!< Windows Logon Screen*/
TERM /*!< Terminal*/
};
/*!
\implements DuplexStream
\brief Stream abstraction for a child process of ILibProcessPipe.
*
The underyling ReadableStream is attached to the child process's <b>stdIn</b>. \n
The underlying WritableStream is attached tot he child process's <b>stdOut</b>.
*/
class ILibProcessPipe_Process
{
public:
/*!
\brief The Child's Process ID
*/
int pid;
/*!
\brief The ReadableStream that is attached to the child process's <b>StdErr</b>
*/
ReadableStream error;
/*!
\brief The 'data' event is emitted data is available from the child process's <b>StdOut</b>.
\param chunk A chunk of data. Can be a Buffer or a string.
*/
void data;
/*!
\brief The 'end' event is emitted when the child process has exited.
*/
void end;
};
};
#endif
void ILibDuktape_ProcessPipe_Init(duk_context *ctx, void *chain);
#endif

View File

@@ -0,0 +1,718 @@
/*
Copyright 2006 - 2017 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_ReadableStream.h"
#include "ILibDuktape_WritableStream.h"
#include "ILibDuktape_Helpers.h"
#include "ILibParsers_Duktape.h"
#include "microstack/ILibParsers.h"
#include "ILibDuktape_EventEmitter.h"
#define ILibDuktape_readableStream_WritePipes "\xFF_WritePipes"
#define ILibDuktape_readableStream_WritePipes_PTRBUFFER "\xFF_WritePipesPtrBuffer"
#define ILibDuktape_readableStream_WritePipes_Stream "\xFF_WritePipes_Stream"
#ifdef __DOXY__
/*!
\implements EventEmitter
\brief Readable streams are an abstraction for a source from which data is consumed
*/
public class ReadableStream
{
public:
/*!
\brief This method returns the current operating state of the ReadableStream.
*
* This is used primarily by the mechanism that underlies the readable.pipe() method.
* In most typical cases, there will be no reason to use this method directly
*/
bool isPaused();
/*!
\brief ReadableStream.pause() method will cause a stream in flowing mode to stop emitting 'data' events, switching out of flowing mode.
*
* Any data that becomes available will remain in the internal buffer.*/
void pause();
/*!
\brief ReadableStream.resume() method causes an explicitly paused ReadableStream to resume emitting 'data' events, switching the stream into flowing mode.
*/
void resume();
/*!
\brief The ReadableStream.pipe() method attaches a WritableStream to the readable, causing it to switch automatically into flowing mode and push all of its data to the attached WritableStream.
*
* Flow control of data will be automatically managed so that the destination WritableStream is not overwhelmed by a faster ReadableStream.
\param destination[in] The WritableStream to attach to the ReadableStream.
*/
void pipe(WritableStream destination);
/*!
\brief The ReadableStream.unpipe() method detaches a WritableStream previously attached using the ReadableStream.pipe() method.
*
\param destination[in] If specified, the WritableStream to detach. If not specified, all streams will be dettached.
*/
void unpipe(WritableStream destination);
/*!
\brief The 'close' event is emitted when the stream and any of its underlying resources have been closed.
*
* The event indicates that no more events will be emitted, and no further computation will occur.
* Not all ReadableStreams will emit the 'close' event.
*/
void close;
/*!
\brief The 'data' event is emitted whenever the stream is relinquishing ownership of a chunk of data to a consumer.
*
* This may occur whenever the stream is switched in flowing mode by calling readable.pipe(), readable.resume(), or by attaching a listener callback to the 'data' event.
\param chunk A chunk of data. Can be a Buffer or a string.
*/
void data;
/*!
\brief The 'end' event is emitted when there is no more data to be consumed from the stream.
*/
void end;
/*!
\brief The 'error' event may be emitted by a Readable implementation at any time.
*
* Typically, this may occur if the underlying stream is unable to generate data due to an underlying internal failure, or when a stream implementation attempts to push an invalid chunk of data.
\param err Error object
*/
void error;
};
#endif
typedef struct ILibDuktape_readableStream_bufferedData
{
struct ILibDuktape_readableStream_bufferedData *Next;
int bufferLen;
char buffer[];
}ILibDuktape_readableStream_bufferedData;
void ILibDuktape_readableStream_WriteData_buffer(ILibDuktape_readableStream *stream, char *buffer, int bufferLen)
{
ILibDuktape_readableStream_bufferedData *buffered = (ILibDuktape_readableStream_bufferedData*)ILibMemory_Allocate(bufferLen + sizeof(ILibDuktape_readableStream_bufferedData), 0, NULL, NULL);
buffered->bufferLen = bufferLen;
memcpy_s(buffered->buffer, bufferLen, buffer, bufferLen);
if (stream->paused_data == NULL)
{
stream->paused_data = buffered;
}
else
{
ILibDuktape_readableStream_bufferedData *tmp = stream->paused_data;
while (tmp->Next != NULL)
{
tmp = tmp->Next;
}
tmp->Next = buffered;
}
if (stream->paused == 0)
{
stream->paused = 1;
stream->PauseHandler(stream, stream->user);
}
}
void ILibDuktape_readableStream_WriteData_OnData_ChainThread(void *chain, void *user)
{
ILibDuktape_readableStream *stream = (ILibDuktape_readableStream*)user;
stream->paused = 0;
duk_push_heapptr(stream->ctx, stream->OnData); // [func]
duk_push_heapptr(stream->ctx, stream->object); // [func][this]
duk_push_heapptr(stream->ctx, stream->extBuffer); // [func][this][buffer]
duk_config_buffer(stream->ctx, -1, stream->extBuffer_buffer, stream->extBuffer_bufferLen);
if (duk_pcall_method(stream->ctx, 1) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(stream->ctx);
}
duk_pop(stream->ctx); // ...
if (stream->paused == 0 && stream->ResumeHandler != NULL) { stream->ResumeHandler(stream, stream->user); }
}
void ILibDuktape_readableStream_WriteData_Flush(struct ILibDuktape_WritableStream *ws, void *user)
{
ILibDuktape_readableStream *stream = (ILibDuktape_readableStream*)user;
#ifdef WIN32
if(InterlockedDecrement(&(stream->pipe_pendingCount)) == 0)
#elif defined(__ATOMIC_SEQ_CST)
if (__atomic_sub_fetch(&(stream->pipe_pendingCount), 1, __ATOMIC_SEQ_CST) == 0)
#else
sem_wait(&(stream->pipeLock));
--stream->pipe_pendingCount;
sem_post(&(stream->pipeLock));
if(stream->pipe_pendingCount == 0)
#endif
{
if (stream->ResumeHandler != NULL) { stream->paused = 0; stream->ResumeHandler(stream, stream->user); }
}
}
duk_ret_t ILibDuktape_readableStream_WriteData_Flush_JS(duk_context *ctx)
{
ILibDuktape_readableStream *stream;
duk_push_current_function(ctx);
duk_get_prop_string(ctx, -1, "readable");
stream = (ILibDuktape_readableStream*)duk_get_pointer(ctx, -1);
ILibDuktape_readableStream_WriteData_Flush(NULL, stream);
return 0;
}
void ILibDuktape_readableStream_WriteData_ChainThread(void *chain, void *user)
{
ILibDuktape_readableStream *stream = (ILibDuktape_readableStream*)user;
ILibDuktape_readableStream_nextWriteablePipe *w;
int jsCount = 0;
sem_wait(&(stream->pipeLock));
w = stream->nextWriteable;
stream->pipe_pendingCount = 0;
while (w != NULL)
{
if (w->nativeWritable != NULL || w->writableStream != NULL) { stream->pipe_pendingCount++; }
w = w->next;
}
w = stream->nextWriteable;
while (w != NULL)
{
if (w->nativeWritable != NULL)
{
ILibDuktape_WritableStream *ws = (ILibDuktape_WritableStream*)w->nativeWritable;
switch (ws->WriteSink(ws, stream->extBuffer_buffer, stream->extBuffer_bufferLen, ws->WriteSink_User))
{
case ILibTransport_DoneState_INCOMPLETE:
ws->OnWriteFlushEx = ILibDuktape_readableStream_WriteData_Flush;
ws->OnWriteFlushEx_User = stream;
break;
case ILibTransport_DoneState_COMPLETE:
ws->OnWriteFlushEx = NULL;
ws->OnWriteFlushEx_User = NULL;
#ifdef WIN32
InterlockedDecrement(&(stream->pipe_pendingCount));
#elif defined(__ATOMIC_SEQ_CST)
__atomic_sub_fetch(&(stream->pipe_pendingCount), 1, __ATOMIC_SEQ_CST);
#else
--stream->pipe_pendingCount;
#endif
break;
case ILibTransport_DoneState_ERROR:
#ifdef WIN32
InterlockedDecrement(&(stream->pipe_pendingCount));
#elif defined(__ATOMIC_SEQ_CST)
__atomic_sub_fetch(&(stream->pipe_pendingCount), 1, __ATOMIC_SEQ_CST);
#else
--stream->pipe_pendingCount;
#endif
break;
}
}
else if(w->writableStream != NULL)
{
duk_push_heapptr(stream->ctx, w->writableStream); // [stream]
duk_get_prop_string(stream->ctx, -1, "write"); // [stream][func]
duk_swap_top(stream->ctx, -2); // [func][this]
duk_push_heapptr(stream->ctx, stream->extBuffer); // [func][this][chunk]
duk_config_buffer(stream->ctx, -1, stream->extBuffer_buffer, stream->extBuffer_bufferLen);
duk_push_c_function(stream->ctx, ILibDuktape_readableStream_WriteData_Flush_JS, DUK_VARARGS); // [func][this][chunk][callback]
duk_push_pointer(stream->ctx, stream); // [func][this][chunk][callback][user]
duk_put_prop_string(stream->ctx, -2, "readable"); // [func][this][chunk][callback]
if (duk_pcall_method(stream->ctx, 2) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(stream->ctx);
}
else
{
jsCount += duk_get_int(stream->ctx, -1);
}
duk_pop(stream->ctx);
}
w = w->next;
}
if (stream->paused != 0 && stream->pipe_pendingCount == 0)
{
sem_post(&(stream->pipeLock));
if (stream->ResumeHandler != NULL) { stream->paused = 0; stream->ResumeHandler(stream, stream->user); }
}
else
{
sem_post(&(stream->pipeLock));
}
}
int ILibDuktape_readableStream_WriteData(ILibDuktape_readableStream *stream, char* buffer, int bufferLen)
{
ILibDuktape_readableStream_nextWriteablePipe *w;
int nonNativeCount = 0;
int nativeCount = 0;
if (stream->paused != 0)
{
ILibDuktape_readableStream_WriteData_buffer(stream, buffer, bufferLen);
return(stream->paused);
}
sem_wait(&(stream->pipeLock));
w = stream->nextWriteable;
while (w != NULL)
{
if (w->nativeWritable == 0) { ++nonNativeCount; }
else { ++nativeCount; }
w = w->next;
}
w = stream->nextWriteable;
if (w != NULL)
{
if (nonNativeCount > 0)
{
// There are piped Pure JavaScript objects... We must context switch to Microstack Thread
stream->extBuffer_buffer = buffer;
stream->extBuffer_bufferLen = bufferLen;
sem_post(&(stream->pipeLock));
if (stream->PauseHandler != NULL) { stream->paused = 1; stream->PauseHandler(stream, stream->user); }
ILibChain_RunOnMicrostackThread(stream->chain, ILibDuktape_readableStream_WriteData_ChainThread, stream);
return(stream->paused);
}
else
{
// All piped objects are native, so we can blast out a send
stream->pipe_pendingCount = nativeCount;
while (w != NULL)
{
if (w->nativeWritable != NULL)
{
ILibDuktape_WritableStream *ws = (ILibDuktape_WritableStream*)w->nativeWritable;
switch (ws->WriteSink(ws, buffer, bufferLen, ws->WriteSink_User))
{
case ILibTransport_DoneState_INCOMPLETE:
ws->OnWriteFlushEx = ILibDuktape_readableStream_WriteData_Flush;
ws->OnWriteFlushEx_User = stream;
break;
case ILibTransport_DoneState_COMPLETE:
ws->OnWriteFlushEx = NULL;
ws->OnWriteFlushEx_User = NULL;
#ifdef WIN32
InterlockedDecrement(&(stream->pipe_pendingCount));
#elif defined(__ATOMIC_SEQ_CST)
__atomic_sub_fetch(&(stream->pipe_pendingCount), 1, __ATOMIC_SEQ_CST);
#else
--stream->pipe_pendingCount;
#endif
break;
case ILibTransport_DoneState_ERROR:
#ifdef WIN32
InterlockedDecrement(&(stream->pipe_pendingCount));
#elif defined(__ATOMIC_SEQ_CST)
__atomic_sub_fetch(&(stream->pipe_pendingCount), 1, __ATOMIC_SEQ_CST);
#else
--stream->pipe_pendingCount;
#endif
break;
}
}
w = w->next;
}
if (stream->pipe_pendingCount == 0)
{
sem_post(&(stream->pipeLock));
return(stream->paused);
}
else
{
sem_post(&(stream->pipeLock));
if (stream->PauseHandler != NULL) { stream->paused = 1; stream->PauseHandler(stream, stream->user); }
return(stream->paused);
}
}
}
else
{
sem_post(&(stream->pipeLock));
}
if (stream->OnData != NULL)
{
if (ILibIsRunningOnChainThread(stream->chain))
{
duk_push_heapptr(stream->ctx, stream->OnData); // [func]
duk_push_heapptr(stream->ctx, stream->object); // [func][this]
duk_push_heapptr(stream->ctx, stream->extBuffer); // [func][this][buffer]
duk_config_buffer(stream->ctx, -1, buffer, bufferLen);
if (duk_pcall_method(stream->ctx, 1) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(stream->ctx);
}
duk_pop(stream->ctx); // ...
}
else
{
// Need to PAUSE, and context switch to Chain Thread, so we can dispatch into JavaScript
if (stream->paused == 0 && stream->PauseHandler != NULL) { stream->paused = 1; stream->PauseHandler(stream, stream->user); }
stream->extBuffer_buffer = buffer;
stream->extBuffer_bufferLen = bufferLen;
ILibChain_RunOnMicrostackThread(stream->chain, ILibDuktape_readableStream_WriteData_OnData_ChainThread, stream);
}
}
else if(stream->PauseHandler != NULL && stream->OnEnd == NULL)
{
// If we get here, it means we are writing data, but nobody is going to be receiving it...
// So we need to buffer the data, so when we are resumed later, we can retry
ILibDuktape_readableStream_WriteData_buffer(stream, buffer, bufferLen);
}
else if (stream->OnEnd != NULL)
{
return 0;
}
return(stream->paused);
}
void ILibDuktape_readableStream_WriteEnd_ChainSink(void *chain, void *user)
{
ILibDuktape_readableStream_WriteEnd((ILibDuktape_readableStream*)user);
}
int ILibDuktape_readableStream_WriteEnd(ILibDuktape_readableStream *stream)
{
int retVal = 1;
if (ILibIsRunningOnChainThread(stream->chain) == 0)
{
// Must context switch to Microstack Thread, in order to dispatch into Java Script
ILibChain_RunOnMicrostackThread(stream->chain, ILibDuktape_readableStream_WriteEnd_ChainSink, stream);
}
else
{
ILibDuktape_readableStream_nextWriteablePipe *next;
if (stream->OnEnd != NULL)
{
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); // ...
retVal = 0;
}
next = stream->nextWriteable;
while (next != NULL)
{
duk_push_heapptr(stream->ctx, next->writableStream); // [stream]
duk_get_prop_string(stream->ctx, -1, "end"); // [stream][func]
duk_swap_top(stream->ctx, -2); // [func][this]
if (duk_pcall_method(stream->ctx, 0) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(stream->ctx);
}
duk_pop(stream->ctx); // ...
next = next->next;
retVal = 0;
}
}
return retVal;
}
void ILibDuktape_readableStream_Closed(ILibDuktape_readableStream *stream)
{
if (stream->OnClose != NULL)
{
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(stream->ctx); // ...
}
}
duk_ret_t ILibDuktape_readableStream_pause(duk_context *ctx)
{
ILibDuktape_readableStream *ptr;
duk_push_this(ctx); // [stream]
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [stream][ptrs]
ptr = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop(ctx); // [stream]
if (ptr->PauseHandler != NULL) { ptr->paused = 1; ptr->PauseHandler(ptr, ptr->user); }
return 1;
}
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)
{
return 1; // No listeners....
}
else if (rs->paused_data == NULL)
{
return 0; // No data was buffered, so we're good
}
else
{
// Let's try to resend as much as we can...
ILibDuktape_readableStream_bufferedData *buffered;
rs->paused = 0;
while ((buffered = rs->paused_data))
{
rs->paused_data = buffered->Next;
if (ILibDuktape_readableStream_WriteData(rs, buffered->buffer, buffered->bufferLen) != 0)
{
// Send did not complete, so lets exit out, and we'll continue next time.
free(buffered);
break;
}
free(buffered);
}
return(rs->paused_data == NULL ? 0 : 1);
}
}
duk_ret_t ILibDuktape_readableStream_resume(duk_context *ctx)
{
ILibDuktape_readableStream *ptr;
duk_push_this(ctx); // [stream]
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [stream][ptrs]
ptr = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop(ctx); // [stream]
if (ILibDuktape_readableStream_resume_flush(ptr) == 0 && ptr->ResumeHandler != NULL) { ptr->paused = 0; ptr->ResumeHandler(ptr, ptr->user); }
return 1;
}
void ILibDuktape_readableStream_pipe_resumeFromTimer(void *obj)
{
ILibDuktape_readableStream* ptr = (ILibDuktape_readableStream*)((void**)obj)[0];
if (ILibDuktape_readableStream_resume_flush(ptr) == 0 && ptr->ResumeHandler != NULL) { ptr->paused = 0; ptr->ResumeHandler(ptr, ptr->user); }
free(obj);
}
void ILibDuktape_readableStream_pipe_resumeFromTimer2(void *obj)
{
free(obj);
}
duk_ret_t ILibDuktape_readableStream_pipe(duk_context *ctx)
{
ILibDuktape_readableStream *rstream;
ILibDuktape_readableStream_nextWriteablePipe *w;
duk_push_this(ctx); // [readable]
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [readable][ptrs]
rstream = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop(ctx); // [readable]
duk_push_object(ctx); // [readable][nextWriteable]
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_readableStream_nextWriteablePipe)); // [readable][nextWriteable][ptrBuffer]
w = (ILibDuktape_readableStream_nextWriteablePipe*)Duktape_GetBuffer(ctx, -1, NULL);
memset(w, 0, sizeof(ILibDuktape_readableStream_nextWriteablePipe));
duk_put_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes_PTRBUFFER); // [readable][nextWriteable]
if (duk_has_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes))
{
// There are already associated pipes
duk_get_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes); // [readable][nextWriteable][prevWriteable]
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_WritePipes_PTRBUFFER); // [readable][nextWriteable][prevWriteable][ptr]
w->next = (ILibDuktape_readableStream_nextWriteablePipe*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop(ctx); // [readable][nextWriteable][prevWriteable]
duk_put_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes); // [readable][nextWriteable]
}
duk_dup(ctx, 0); // [readable][nextWriteable][stream]
if (duk_has_prop_string(ctx, -1, ILibDuktape_WritableStream_WSPTRS))
{
// This is one of our writable stream implementation... So we can keep everything native
duk_get_prop_string(ctx, -1, ILibDuktape_WritableStream_WSPTRS); // [readable][nextWriteable][stream][buffer]
w->nativeWritable = Duktape_GetBuffer(ctx, -1, NULL);
duk_pop(ctx); // [readable][nextWriteable][stream]
}
w->writableStream = duk_get_heapptr(ctx, -1);
duk_put_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes_Stream); // [readable][nextWriteable]
rstream->nextWriteable = w;
// Save to the readableStream
duk_put_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes); // [readable]
duk_dup(ctx, 0); // [readable][writable]
if (duk_has_prop_string(ctx, -1, "emit"))
{
duk_push_string(ctx, "emit"); // [readable][writable][key]
duk_push_string(ctx, "pipe"); // [readable][writable][key][eventName]
duk_dup(ctx, -4); // [readable][writable][key][eventName][readable]
if (duk_pcall_prop(ctx, -4, 2) != 0) // [readable][writable][retVal/err]
{
ILibDuktape_Process_UncaughtException(ctx);
}
duk_pop_2(ctx); // [readable]
}
else
{
duk_pop(ctx);
}
if (rstream->paused != 0)
{
void *chain = Duktape_GetChain(ctx);
if (chain != NULL)
{
// We are paused, so we should yield and resume... We yield, so in case the user tries to chain multiple pipes, it will chain first
void **tmp = (void**)ILibMemory_Allocate(sizeof(void*), 0, NULL, NULL);
tmp[0] = rstream;
ILibLifeTime_AddEx(ILibGetBaseTimer(chain), tmp, 0, ILibDuktape_readableStream_pipe_resumeFromTimer, ILibDuktape_readableStream_pipe_resumeFromTimer2);
}
else
{
// Oops
duk_push_string(ctx, "ILibParsers_Duktape *MISSING*");
duk_throw(ctx);
return(DUK_RET_ERROR);
}
}
if (rstream->PipeHookHandler != NULL) { rstream->PipeHookHandler(rstream, rstream->user); }
return 1;
}
duk_ret_t ILibDuktape_readableStream_unpipe(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
ILibDuktape_readableStream *data;
ILibDuktape_readableStream_nextWriteablePipe *w, *prev;
duk_push_this(ctx); // [stream]
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [stream][ptrs]
data = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
if (nargs == 0)
{
duk_del_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes);
data->nextWriteable = NULL;
}
else if (data->nextWriteable != NULL)
{
w = data->nextWriteable;
prev = NULL;
while (w != NULL)
{
if (w->writableStream == duk_get_heapptr(ctx, 0))
{
memset(w, 0, 2 * sizeof(void*));
if (data->nextWriteable == w)
{
//printf("Unpiping object: %p\n", (void*)w);
data->nextWriteable = w->next;
break;
}
else
{
prev->next = w->next;
break;
}
}
else
{
prev = w;
w = w->next;
}
}
}
return 0;
}
duk_ret_t ILibDuktape_readableStream_isPaused(duk_context *ctx)
{
ILibDuktape_readableStream *data;
duk_push_this(ctx); // [stream]
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [stream][ptrs]
data = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
if (data->paused == 0)
{
duk_push_false(ctx);
}
else
{
duk_push_true(ctx);
}
return 1;
}
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)
{
ILibDuktape_readableStream_bufferedData *tmp;
ILibDuktape_readableStream *ptrs;
duk_push_heapptr(ctx, stream); // [stream]
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [stream][buffer]
ptrs = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
while ((tmp = (ILibDuktape_readableStream_bufferedData*)ptrs->paused_data) != NULL)
{
tmp = tmp->Next;
free(ptrs->paused_data);
ptrs->paused_data = tmp;
}
sem_destroy(&(ptrs->pipeLock));
duk_pop_2(ctx);
}
ILibDuktape_readableStream* ILibDuktape_InitReadableStream(duk_context *ctx, ILibDuktape_readableStream_PauseResumeHandler OnPause, ILibDuktape_readableStream_PauseResumeHandler OnResume, void *user)
{
ILibDuktape_readableStream *retVal;
ILibDuktape_EventEmitter *emitter;
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_readableStream)); // [obj][buffer]
duk_dup(ctx, -1); // [obj][buffer][buffer]
duk_put_prop_string(ctx, -3, ILibDuktape_readableStream_RSPTRS); // [obj][buffer]
retVal = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL); // [obj][buffer]
memset(retVal, 0, sizeof(ILibDuktape_readableStream));
duk_pop(ctx); // [obj]
duk_push_external_buffer(ctx); // [obj][extBuffer]
retVal->extBuffer = duk_get_heapptr(ctx, -1);
duk_put_prop_string(ctx, -2, "_extBuffer"); // [obj]
retVal->ctx = ctx;
retVal->chain = Duktape_GetChain(ctx);
retVal->object = duk_get_heapptr(ctx, -1);
retVal->user = user;
retVal->PauseHandler = OnPause;
retVal->ResumeHandler = OnResume;
sem_init(&(retVal->pipeLock), 0, 1);
ILibDuktape_CreateIndependentFinalizer(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));
ILibDuktape_CreateInstanceMethod(ctx, "pause", ILibDuktape_readableStream_pause, 0);
ILibDuktape_CreateInstanceMethod(ctx, "resume", ILibDuktape_readableStream_resume, 0);
ILibDuktape_CreateEventWithGetter(ctx, "pipe", ILibDuktape_readableStream_pipe_getter);
ILibDuktape_CreateInstanceMethod(ctx, "unpipe", ILibDuktape_readableStream_unpipe, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "isPaused", ILibDuktape_readableStream_isPaused, 0);
return retVal;
}

View File

@@ -0,0 +1,73 @@
/*
Copyright 2006 - 2017 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_READABLESTREAM___
#define ___ILIBDUKTAPE_READABLESTREAM___
#include "duktape.h"
#include "microstack/ILibParsers.h"
#define ILibDuktape_readableStream_RSPTRS "\xFF_ReadableStream_PTRS"
struct ILibDuktape_readableStream;
typedef void(*ILibDuktape_readableStream_PauseResumeHandler)(struct ILibDuktape_readableStream *sender, void *user);
typedef void(*ILibDuktape_readableStream_MethodHookHandler)(struct ILibDuktape_readableStream *sender, void *user);
typedef struct ILibDuktape_readableStream_nextWriteablePipe
{
void *writableStream;
void *nativeWritable;
struct ILibDuktape_readableStream_nextWriteablePipe *next;
}ILibDuktape_readableStream_nextWriteablePipe;
typedef struct ILibDuktape_readableStream
{
duk_context *ctx;
void *chain;
void *object;
void *OnClose;
void *OnData;
void *OnEnd;
void *extBuffer;
char *extBuffer_buffer;
int extBuffer_bufferLen;
void *user;
ILibDuktape_readableStream_nextWriteablePipe *nextWriteable;
sem_t pipeLock;
#if defined(WIN32)
volatile LONG pipe_pendingCount; // Use Windows Built-in Atomic Intrinsics
#elif defined(__ATOMIC_SEQ_CST)
volatile int pipe_pendingCount; // Use GCC Built-in Atomic Intrinsics
#else
int pipe_pendingCount; // No Atomic Built-ins... Use a Mutex
#endif
int paused;
void *paused_data;
ILibDuktape_readableStream_PauseResumeHandler PauseHandler;
ILibDuktape_readableStream_PauseResumeHandler ResumeHandler;
ILibDuktape_readableStream_MethodHookHandler PipeHookHandler;
}ILibDuktape_readableStream;
ILibDuktape_readableStream* ILibDuktape_InitReadableStream(duk_context *ctx, ILibDuktape_readableStream_PauseResumeHandler OnPause, ILibDuktape_readableStream_PauseResumeHandler OnResume, void *user);
#define ILibDuktape_ReadableStream_Init(ctx, OnPause, OnResume, user) ILibDuktape_InitReadableStream(ctx, OnPause, OnResume, user)
#define ILibDuktape_readableStream_SetPauseResumeHandlers(stream, PauseFunc, ResumeFunc, userObj) ((ILibDuktape_readableStream*)stream)->PauseHandler = PauseFunc; ((ILibDuktape_readableStream*)stream)->ResumeHandler = ResumeFunc; ((ILibDuktape_readableStream*)stream)->user = userObj;
int ILibDuktape_readableStream_WriteData(ILibDuktape_readableStream *stream, char* buffer, int bufferLen);
int ILibDuktape_readableStream_WriteEnd(ILibDuktape_readableStream *stream);
void ILibDuktape_readableStream_Closed(ILibDuktape_readableStream *stream);
#endif

View File

@@ -0,0 +1,477 @@
#include "ILibDuktape_SHA256.h"
#include "duktape.h"
#include "ILibDuktape_Helpers.h"
#include "ILibDuktape_WritableStream.h"
#include "ILibDuktapeModSearch.h"
#include "ILibDuktape_EventEmitter.h"
#include "../microstack/ILibCrypto.h"
#define ILibDuktape_MD5_PTR "\xFF_MD5PTR"
#define ILibDuktape_SHA256_PTR "\xFF_SHA256PTR"
#define ILibDuktape_SHA256_SIGNER_PTR "\xFF_SHA256_SIGNER_PTR"
#define ILibDuktape_SHA256_SIGNER_CERT "\xFF_SHA256_SIGNER_CERT"
#define ILibDuktape_SHA256_SIGNER_CERT_ALLOC "\xFF_SHA256_SIGNER_CERT_ALLOC"
#define ILibDuktape_SHA256_SIGNER_SIGBUFFER "\xFF_SHA256_SIGNER_SIG_BUFFER"
#ifndef MICROSTACK_NOTLS
typedef struct ILibDuktape_SHA256_Data
{
duk_context *ctx;
void *object;
void *OnHash;
void *OnHashString;
char buffer[33];
SHA256_CTX shctx;
}ILibDuktape_SHA256_Data;
typedef struct ILibDuktape_MD5_Data
{
duk_context *ctx;
void *object;
void *OnHash;
void *OnHashString;
char buffer[33];
MD5_CTX mctx;
}ILibDuktape_MD5_Data;
typedef struct ILibDuktape_SHA256_Signer_Data
{
duk_context *ctx;
EVP_MD_CTX *mdctx;
void *obj;
ILibDuktape_WritableStream *writableStream;
void *OnSignature;
void *OnSignatureString;
}ILibDuktape_SHA256_Signer_Data;
duk_ret_t ILibDuktape_SHA256_Finalizer(duk_context *ctx)
{
return 0;
}
ILibTransport_DoneState ILibDuktape_SHA256_Write(struct ILibDuktape_WritableStream *stream, char *buffer, int bufferLen, void *user)
{
ILibDuktape_SHA256_Data *data = (ILibDuktape_SHA256_Data*)user;
SHA256_Update(&(data->shctx), buffer, bufferLen);
return(ILibTransport_DoneState_COMPLETE);
}
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_ret_t ILibDuktape_SHA256_SIGNER_Finalizer(duk_context *ctx)
{
ILibDuktape_SHA256_Signer_Data *data;
duk_get_prop_string(ctx, 0, ILibDuktape_SHA256_SIGNER_PTR);
data = (ILibDuktape_SHA256_Signer_Data*)Duktape_GetBuffer(ctx, -1, NULL);
if (data->mdctx != NULL)
{
EVP_MD_CTX_destroy(data->mdctx);
data->mdctx = NULL;
}
return 0;
}
void ILibDuktape_SHA256_SIGNER_End(struct ILibDuktape_WritableStream *stream, void *user)
{
ILibDuktape_SHA256_Signer_Data *data = (ILibDuktape_SHA256_Signer_Data*)user;
size_t len;
char *buffer;
EVP_DigestSignFinal(data->mdctx, NULL, &len);
duk_push_heapptr(data->ctx, data->obj); // [signer]
duk_push_fixed_buffer(data->ctx, len); // [signer][sigBuffer]
buffer = (char*)Duktape_GetBuffer(data->ctx, -1, NULL);
duk_put_prop_string(data->ctx, -2, ILibDuktape_SHA256_SIGNER_SIGBUFFER); // [signer]
EVP_DigestSignFinal(data->mdctx, (unsigned char*)buffer, &len);
if (data->OnSignature != NULL)
{
duk_get_prop_string(data->ctx, -1, ILibDuktape_SHA256_SIGNER_SIGBUFFER); // [signer][sigBuffer]
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]
if (duk_pcall_method(data->ctx, 1) != 0) { ILibDuktape_Process_UncaughtException(data->ctx); } // ...
}
duk_pop(data->ctx); // ...
}
ILibTransport_DoneState ILibDuktape_SHA256_SIGNER_Write(struct ILibDuktape_WritableStream *stream, char *buffer, int bufferLen, void *user)
{
ILibDuktape_SHA256_Signer_Data *data = (ILibDuktape_SHA256_Signer_Data*)user;
EVP_DigestSignUpdate(data->mdctx, buffer, bufferLen);
return(ILibTransport_DoneState_COMPLETE);
}
duk_ret_t ILibDuktape_SHA256_VERIFIER_Create(duk_context *ctx)
{
//ILibDuktape_SHA256_Signer_Data *data;
//duk_push_this(ctx); // [signer]
//duk_get_prop_string(ctx, -1, ILibDuktape_SHA256_SIGNER_PTR); // [signer][ptr]
//data = (ILibDuktape_SHA256_Signer_Data*)Duktape_GetBuffer(ctx, -1, NULL);
//duk_pop(ctx); // [signer]
return(ILibDuktape_Error(ctx, "Not implemented"));
}
duk_ret_t ILibDuktape_SHA256_SIGNER_Create(duk_context *ctx)
{
ILibDuktape_SHA256_Signer_Data *data;
struct util_cert *cert;
duk_push_this(ctx); // [signer]
duk_get_prop_string(ctx, -1, ILibDuktape_SHA256_SIGNER_PTR); // [signer][ptr]
data = (ILibDuktape_SHA256_Signer_Data*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop(ctx); // [signer]
if (duk_has_prop_string(ctx, 0, "MeshAgent"))
{
duk_get_prop_string(ctx, 0, "MeshAgent");
duk_get_prop_string(ctx, -1, ILibDuktape_MeshAgent_Cert_NonLeaf);
cert = (struct util_cert*)duk_get_pointer(ctx, -1);
}
else if (duk_has_prop_string(ctx, 0, "pfx") && duk_has_prop_string(ctx, 0, "passphrase"))
{
char *pfx;
duk_size_t pfxLen;
char *passphrase;
duk_get_prop_string(ctx, 0, "passphrase"); // [signer][passphrase]
passphrase = (char*)duk_get_string(ctx, -1);
duk_pop(ctx); // [signer]
duk_get_prop_string(ctx, 0, "pfx"); // [signer][pfx]
pfx = Duktape_GetBuffer(ctx, -1, &pfxLen);
duk_pop(ctx); // [signer]
duk_push_fixed_buffer(ctx, sizeof(struct util_cert)); // [signer][buffer]
cert = (struct util_cert*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, ILibDuktape_SHA256_SIGNER_CERT); // [signer]
if (util_from_p12(pfx, (int)pfxLen, passphrase, cert) == 0)
{
duk_push_string(ctx, "SHA256_Signer_Create: Invalid PFX/Passphrase");
duk_throw(ctx);
return(DUK_RET_ERROR);
}
else
{
duk_push_boolean(ctx, 1); // [signer][cert-alloc]
duk_put_prop_string(ctx, -2, ILibDuktape_SHA256_SIGNER_CERT_ALLOC); // [signer]
}
}
else if (duk_has_prop_string(ctx, 0, ILibDuktape_MeshAgent_Cert_NonLeaf))
{
duk_get_prop_string(ctx, 0, ILibDuktape_MeshAgent_Cert_NonLeaf); // [signer][cert]
cert = (struct util_cert*)duk_get_pointer(ctx, -1);
duk_pop(ctx); // [signer]
}
else
{
duk_push_string(ctx, "SHA256_Signer_Create: Unrecognized paramter");
duk_throw(ctx);
return(DUK_RET_ERROR);
}
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_SHA256_SIGNER_Finalizer);
data->mdctx = EVP_MD_CTX_create();
EVP_DigestSignInit(data->mdctx, NULL, EVP_sha256(), NULL, cert->pkey);
data->writableStream = ILibDuktape_WritableStream_Init(ctx, ILibDuktape_SHA256_SIGNER_Write, ILibDuktape_SHA256_SIGNER_End, data);
ILibDuktape_CreateEventWithSetter(ctx, "OnSignature", "\xFF_OnSignature", &(data->OnSignature));
return 1;
}
void ILibDuktape_SHA256_SIGNER_PUSH(duk_context *ctx, void *chain)
{
ILibDuktape_SHA256_Signer_Data* data;
duk_push_object(ctx); // [signer]
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_SHA256_Signer_Data)); // [signer][data]
data = (ILibDuktape_SHA256_Signer_Data*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, ILibDuktape_SHA256_SIGNER_PTR); // [signer]
memset(data, 0, sizeof(ILibDuktape_SHA256_Signer_Data));
data->obj = duk_get_heapptr(ctx, -1);
data->ctx = ctx;
ILibDuktape_CreateInstanceMethod(ctx, "Create", ILibDuktape_SHA256_SIGNER_Create, 1);
}
void ILibDuktape_SHA256_VERIFY_PUSH(duk_context *ctx, void *chain)
{
ILibDuktape_SHA256_Signer_Data* data;
duk_push_object(ctx); // [signer]
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_SHA256_Signer_Data)); // [signer][data]
data = (ILibDuktape_SHA256_Signer_Data*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, ILibDuktape_SHA256_SIGNER_PTR); // [signer]
memset(data, 0, sizeof(ILibDuktape_SHA256_Signer_Data));
data->obj = duk_get_heapptr(ctx, -1);
data->ctx = ctx;
ILibDuktape_CreateInstanceMethod(ctx, "Create", ILibDuktape_SHA256_VERIFIER_Create, 1);
}
duk_ret_t ILibDuktape_SHA256_syncHash(duk_context *ctx)
{
ILibDuktape_SHA256_Data *data;
duk_size_t bufferLen;
char *buffer = Duktape_GetBuffer(ctx, 0, &bufferLen);
duk_push_this(ctx); // [sha]
duk_get_prop_string(ctx, -1, ILibDuktape_SHA256_PTR);
data = (ILibDuktape_SHA256_Data*)Duktape_GetBuffer(ctx, -1, NULL);
SHA256_Init(&(data->shctx));
SHA256_Update(&(data->shctx), buffer, bufferLen);
SHA256_Final((unsigned char*)data->buffer, &(data->shctx));
data->buffer[32] = 0;
duk_push_current_function(ctx);
duk_get_prop_string(ctx, -1, "strRet");
if (duk_get_boolean(ctx, -1) == 0)
{
duk_push_external_buffer(ctx);
duk_config_buffer(ctx, -1, data->buffer, 32);
}
else
{
util_tohex(data->buffer, 32, ILibScratchPad);
duk_push_string(ctx, ILibScratchPad);
}
return(1);
}
ILibTransport_DoneState ILibDuktape_MD5_Write(struct ILibDuktape_WritableStream *stream, char *buffer, int bufferLen, void *user)
{
ILibDuktape_MD5_Data *data = (ILibDuktape_MD5_Data*)user;
MD5_Update(&(data->mctx), buffer, bufferLen);
return(ILibTransport_DoneState_COMPLETE);
}
void ILibDuktape_MD5_End(struct ILibDuktape_WritableStream *stream, void *user)
{
ILibDuktape_MD5_Data *data = (ILibDuktape_MD5_Data*)user;
data->buffer[32] = 0;
MD5_Final((unsigned char*)data->buffer, &(data->mctx));
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_ret_t ILibDuktape_MD5_syncHash(duk_context *ctx)
{
ILibDuktape_MD5_Data *data;
duk_size_t bufferLen;
char *buffer = Duktape_GetBuffer(ctx, 0, &bufferLen);
duk_push_this(ctx); // [sha]
duk_get_prop_string(ctx, -1, ILibDuktape_MD5_PTR);
data = (ILibDuktape_MD5_Data*)Duktape_GetBuffer(ctx, -1, NULL);
MD5_Init(&(data->mctx));
MD5_Update(&(data->mctx), buffer, bufferLen);
MD5_Final((unsigned char*)data->buffer, &(data->mctx));
data->buffer[32] = 0;
duk_push_current_function(ctx);
duk_get_prop_string(ctx, -1, "strRet");
if (duk_get_boolean(ctx, -1) == 0)
{
duk_push_external_buffer(ctx);
duk_config_buffer(ctx, -1, data->buffer, 32);
}
else
{
util_tohex(data->buffer, 32, ILibScratchPad);
duk_push_string(ctx, ILibScratchPad);
}
return(1);
}
duk_ret_t ILibDuktape_MD5_Create(duk_context *ctx)
{
ILibDuktape_MD5_Data *data;
ILibDuktape_EventEmitter *emitter;
duk_push_object(ctx); // [md5]
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_MD5_Data)); // [md5][buffer]
data = (ILibDuktape_MD5_Data*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, ILibDuktape_MD5_PTR); // [md5]
emitter = ILibDuktape_EventEmitter_Create(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));
data->ctx = ctx;
data->object = duk_get_heapptr(ctx, -1);
MD5_Init(&(data->mctx));
ILibDuktape_WritableStream_Init(ctx, ILibDuktape_MD5_Write, ILibDuktape_MD5_End, data);
return(1);
}
duk_ret_t ILibDuktape_SHA256_Create(duk_context *ctx)
{
ILibDuktape_SHA256_Data *data;
ILibDuktape_EventEmitter *emitter;
duk_push_object(ctx); // [sha]
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_SHA256_Data)); // [sha][buffer]
data = (ILibDuktape_SHA256_Data*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, ILibDuktape_SHA256_PTR); // [sha]
emitter = ILibDuktape_EventEmitter_Create(ctx);
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_SHA256_Finalizer);
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));
data->ctx = ctx;
data->object = duk_get_heapptr(ctx, -1);
SHA256_Init(&(data->shctx));
ILibDuktape_WritableStream_Init(ctx, ILibDuktape_SHA256_Write, ILibDuktape_SHA256_End, data);
return(1);
}
void ILibDuktape_SHA256_PUSH(duk_context *ctx, void *chain)
{
duk_push_object(ctx); // [sha]
ILibDuktape_CreateInstanceMethod(ctx, "create", ILibDuktape_SHA256_Create, 0);
}
void ILibDuktape_MD5_PUSH(duk_context *ctx, void *chain)
{
duk_push_object(ctx); // [md5]
ILibDuktape_CreateInstanceMethod(ctx, "create", ILibDuktape_MD5_Create, 0);
}
#endif
void ILibDuktape_SHA256_Init(duk_context * ctx)
{
#ifndef MICROSTACK_NOTLS
ILibDuktape_ModSearch_AddHandler(ctx, "SHA256Stream_Signer", ILibDuktape_SHA256_SIGNER_PUSH);
ILibDuktape_ModSearch_AddHandler(ctx, "SHA256Stream_Verifier", ILibDuktape_SHA256_VERIFY_PUSH);
ILibDuktape_ModSearch_AddHandler(ctx, "SHA256Stream", ILibDuktape_SHA256_PUSH);
ILibDuktape_ModSearch_AddHandler(ctx, "MD5Stream", ILibDuktape_MD5_PUSH);
#endif
}
#ifdef __DOXY__
/*!
\implements WritableStream
\brief WritableStream that exposes MD5 Hashing functionality. <b>Note:</b> To use, must <b>require('MD5Stream')</b>
*/
class MD5Stream
{
public:
/*!
\brief Performs an MD5 Hash of the data passed to this method
\param data \<Buffer\|String\> The data to hash
\return <Buffer> The MD5 hash of the supplied data
*/
Buffer syncHash(data);
/*!
\brief Performs an MD5 Hash of the data passed to this method, and returns the result as a Hex String
\param data \<Buffer\|String\> The data to hash
\return \<String\> The MD5 hash of the supplied data, as a Hex String
*/
String syncHashString(data);
/*!
\brief event dispatched when the WritableStream is finished
\param data <Buffer> The MD5 Hash of the data fed thru the WritableStream
*/
void hash;
/*!
\brief event dispatched when the WritableStream is finished
\param data \<String\> The MD5 Hash of the data fed thru the WritableStream, as a Hex String.
*/
void hashString;
};
/*!
\implements WritableStream
\brief WritableStream that exposes SHA256 Hashing functionality. <b>Note:</b> To use, must <b>require('SHA256Stream')</b>
*/
class SHA256Stream
{
public:
/*!
\brief Performs a SHA256 Hash of the data passed to this method
\param data \<Buffer\|String\> The data to hash
\return <Buffer> The SHA256 hash of the supplied data
*/
Buffer syncHash(data);
/*!
\brief Performs a SHA256 Hash of the data passed to this method, and returns the result as a Hex String
\param data \<Buffer\|String\> The data to hash
\return \<String\> The SHA256 hash of the supplied data, as a Hex String
*/
String syncHashString(data);
/*!
\brief event dispatched when the WritableStream is finished
\param data <Buffer> The SHA256 Hash of the data fed thru the WritableStream
*/
void hash;
/*!
\brief event dispatched when the WritableStream is finished
\param data \<String\> The SHA256 Hash of the data fed thru the WritableStream, as a Hex String.
*/
void hashString;
};
#endif

View File

@@ -0,0 +1,10 @@
#ifndef ___DUKTAPE_SHA256___
#define ___DUKTAPE_SHA256___
#include "duktape.h"
void ILibDuktape_SHA256_Init(duk_context *ctx);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,158 @@
/*
Copyright 2006 - 2017 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_SCRIPTCONTAINER__
#define __ILIBDUKTAPE_SCRIPTCONTAINER__
#include "microscript/duktape.h"
#include "ILibDuktape_Helpers.h"
#include "../microstack/ILibProcessPipe.h"
#include "../microstack/ILibSimpleDataStore.h"
#ifdef __DOXY__
/*!
\brief Process Encapsulation for a JavaScript engine. To use, must <b>require('ScriptContainer')</b>
*/
class MasterScriptContainer
{
public:
/*!
\brief Event emitted when the parent container has sent an out of band data object. <B>Note: </b>Only exposed if the currently executing code is running in a process isolated container
\param obj The object that was received
*/
void data;
/*!
\brief Sends out of band data to the parent container. <B>Note: </b>Only exposed if the currently executing code is running in a process isolated container
\param obj The object to send to the parent container
*/
void send(obj);
/*!
\brief Creates a ChildScriptContainer that is process isolated from the parent.
*
ChildScriptContainer Create(executionTimeout, permissions[, userType]);
\param executionTimeout <int> Specifies the number of seconds that execution must complete, before the process is terminated. <b>0</b> means no limit.
\param permissions <ContainerPermissions> ContainerPermissions specifying what permissions the child container will have. Default is all.
\param userType <ContainerUserTypes> Optional ContainerUserTypes specifying the type of process isolation.
\return ChildScriptContainer result
*/
ChildScriptContainer Create(executionTimeout, permissions[, userType]);
/*!
\brief Enumeration describing the permissions executing java script will have
*/
enum ContainerPermissions
{
DEFAULT, //!< All Access
NO_AGENT,//!< MeshAgent object will not be accessible
NO_MARSHAL,//!< _GenericMarshal class will not be accessible
NO_PROCESS_SPAWNING, //!< ILibProcessPipe class will not be accessible
NO_FILE_SYSTEM_ACCESS,//!< fs class will not be accessible
NO_NETWORK_ACCESS//!< Networking classes will not be accessible
};
/*!
\brief Abstraction for a process isolated Java Script Engine.
*/
class ChildScriptContainer
{
public:
/*!
\brief Event emitted when the child process has exited
\param code <int> The code that the child process exited with
*/
void exit;
/*!
\brief Event emitted when an exception has occured
\param err Error object representing the exception that occured
*/
void error;
/*!
\brief Event emitted when the child container has sent an out of band data object
\param obj The object that was received
*/
void data;
/*!
\brief Signals the child process to terminate
*/
void exit();
/*!
\brief Executes the supplied javascript in the context of the child container
\param script <String | Buffer> The JavaScript to execute
\param callback Optional callback that will get dispatched with the return value of the specified script. <b>Undefined</b> will be passed if there was no return value.
*/
void ExecuteString(script[, callback]);
/*!
\brief Sends out of band data to the child container
\param obj The object to send to the child container
*/
void send(obj);
/*!
\brief Supplies JavaScript modules to the ChildScriptContainer
\param name \<String\> The name to associate with the supplied module
\param module <String | Buffer> The module to send to the ChildScriptContainer.
*/
void addModule(name, module);
};
};
#endif
typedef enum SCRIPT_ENGINE_SECURITY_FLAGS
{
SCRIPT_ENGINE_NO_MESH_AGENT_ACCESS = 0x10000000,
SCRIPT_ENGINE_NO_GENERIC_MARSHAL_ACCESS = 0x08000000,
SCRIPT_ENGINE_NO_PROCESS_SPAWNING = 0x04000000,
SCRIPT_ENGINE_NO_FILE_SYSTEM_ACCESS = 0x00000001,
SCRIPT_ENGINE_NO_NETWORK_ACCESS = 0x00000002,
}SCRIPT_ENGINE_SECURITY_FLAGS;
typedef struct SCRIPT_ENGINE_SETTINGS
{
void *chain;
SCRIPT_ENGINE_SECURITY_FLAGS securityFlags;
unsigned int executionTimeout;
ILibSimpleDataStore db;
ILibDuktape_HelperEvent exitHandler;
void *exitUserObject;
ILibDuktape_NativeUncaughtExceptionHandler nExeptionHandler;
void* nExceptionUserObject;
char *exePath;
ILibProcessPipe_Manager pipeManager;
char *argList[];
}SCRIPT_ENGINE_SETTINGS;
void ILibDuktape_ScriptContainer_InitMaster(void *chain, char *exePath, ILibProcessPipe_Manager manager);
int ILibDuktape_ScriptContainer_StartSlave(void *chain, ILibProcessPipe_Manager manager);
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_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);
int ILibDuktape_ScriptContainer_CompileJavaScript(duk_context *ctx, char *payload, int payloadLen);
int ILibDuktape_ScriptContainer_CompileJavaScript_FromFile(duk_context *ctx, char *path, int pathLen);
int ILibDuktape_ScriptContainer_ExecuteByteCode(duk_context *ctx);
#endif

View File

@@ -0,0 +1,286 @@
/*
Copyright 2006 - 2017 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_SimpleDataStore.h"
#include "microstack/ILibParsers.h"
#include "ILibDuktapeModSearch.h"
#include "ILibDuktape_Helpers.h"
#include "microstack/ILibSimpleDataStore.h"
#define ILibDuktape_DataStore_PTR "\xFF_DataStorePTR"
typedef struct ILibDuktape_SimpleDataStore_Enumerator
{
duk_context *ctx;
int count;
char* GuidHex;
int GuidHexLen;
}ILibDuktape_SimpleDataStore_Enumerator;
duk_ret_t ILibDuktape_SimpleDataStore_Finalizer(duk_context *ctx)
{
ILibSimpleDataStore dataStore;
duk_get_prop_string(ctx, 0, ILibDuktape_DataStore_PTR); // [dataStore]
dataStore = (ILibSimpleDataStore)duk_to_pointer(ctx, -1);
ILibSimpleDataStore_Close(dataStore);
return 0;
}
duk_ret_t ILibDuktape_SimpleDataStore_Put(duk_context *ctx)
{
char *cguid = Duktape_GetContextGuidHex(ctx);
duk_size_t keyLen;
char *key;
char *value;
duk_size_t valueLen;
ILibSimpleDataStore dataStore;
if (!duk_is_string(ctx, 0)) { return(ILibDuktape_Error(ctx, "SimpleDataStore.Put(): 'key' invalid parameter")); }
key = (char*)duk_get_lstring(ctx, 0, &keyLen);
if (duk_is_string(ctx, 1))
{
value = (char*)duk_get_lstring(ctx, 1, &valueLen);
++valueLen;
}
else
{
value = Duktape_GetBuffer(ctx, 1, &valueLen);
}
duk_push_this(ctx); // [ds]
duk_get_prop_string(ctx, -1, ILibDuktape_DataStore_PTR); // [ds][ptr]
dataStore = (ILibSimpleDataStore)duk_to_pointer(ctx, -1);
if (cguid != NULL)
{
keyLen = sprintf_s(ILibScratchPad2, sizeof(ILibScratchPad2), "%s/%s", cguid, key);
key = ILibScratchPad2;
}
duk_push_int(ctx, ILibSimpleDataStore_PutEx(dataStore, key, (int)keyLen, value, (int)valueLen)); // [ds][ptr][retVal]
return 1;
}
duk_ret_t ILibDuktape_SimpleDataStore_Get(duk_context *ctx)
{
char *cguid = Duktape_GetContextGuidHex(ctx);
char *key = (char*)duk_require_string(ctx, 0);
ILibSimpleDataStore dataStore;
char *buffer;
int bufferSize;
int written;
duk_push_this(ctx); // [ds]
duk_get_prop_string(ctx, -1, ILibDuktape_DataStore_PTR); // [ds][ptr]
dataStore = (ILibSimpleDataStore)duk_to_pointer(ctx, -1);
if (cguid != NULL)
{
sprintf_s(ILibScratchPad2, sizeof(ILibScratchPad2), "%s/%s", cguid, key);
key = ILibScratchPad2;
}
bufferSize = ILibSimpleDataStore_Get(dataStore, key, NULL, 0);
if (bufferSize == 0)
{
duk_push_null(ctx);
return 1;
}
duk_push_fixed_buffer(ctx, bufferSize); // [ds][ptr][buffer]
buffer = Duktape_GetBuffer(ctx, -1, NULL);
written = ILibSimpleDataStore_Get(dataStore, key, buffer, bufferSize);
if (written != bufferSize)
{
duk_push_null(ctx); // [ds][ptr][buffer][null]
}
else
{
if (buffer[bufferSize - 1] == 0)
{
int i = 0;
for (i = 0; i < bufferSize - 1; ++i)
{
if (buffer[i] == 0)
{
break;
}
}
if (i == bufferSize - 1)
{
duk_push_string(ctx, buffer);
}
}
}
return 1;
}
duk_ret_t ILibDuktape_SimpleDataStore_Compact(duk_context *ctx)
{
ILibSimpleDataStore dataStore;
duk_push_this(ctx); // [ds]
duk_get_prop_string(ctx, -1, ILibDuktape_DataStore_PTR); // [ds][ptr]
dataStore = (ILibSimpleDataStore)duk_to_pointer(ctx, -1);
duk_push_int(ctx, ILibSimpleDataStore_Compact(dataStore)); // [ds][ptr][retVal]
return 1;
}
void ILibDuktape_SimpleDataStore_Keys_EnumerationSink(ILibSimpleDataStore sender, char* Key, int KeyLen, void *user)
{
ILibDuktape_SimpleDataStore_Enumerator * en = (ILibDuktape_SimpleDataStore_Enumerator*)user;
if (en->GuidHex == NULL || (KeyLen > en->GuidHexLen && memcmp(en->GuidHex, Key, en->GuidHexLen) == 0))
{
if (en->GuidHex != NULL)
{
duk_push_lstring(en->ctx, Key + en->GuidHexLen, KeyLen - en->GuidHexLen);
}
else
{
duk_push_lstring(en->ctx, Key, KeyLen);
}
duk_put_prop_index(en->ctx, -2, en->count++);
}
}
duk_ret_t ILibDuktape_SimpleDataStore_Keys(duk_context *ctx)
{
ILibSimpleDataStore ds;
ILibDuktape_SimpleDataStore_Enumerator enumerator;
memset(&enumerator, 0, sizeof(ILibDuktape_SimpleDataStore_Enumerator));
duk_push_this(ctx); // [DataStore]
duk_get_prop_string(ctx, -1, ILibDuktape_DataStore_PTR); // [DataStore][ptr]
ds = (ILibSimpleDataStore)duk_get_pointer(ctx, -1);
enumerator.ctx = ctx;
enumerator.count = 0;
enumerator.GuidHex = Duktape_GetContextGuidHex(ctx);
if (enumerator.GuidHex != NULL)
{
enumerator.GuidHexLen = 1 + (int)strnlen_s(enumerator.GuidHex, sizeof(ILibScratchPad));
enumerator.GuidHex[enumerator.GuidHexLen - 1] = '/';
enumerator.GuidHex[enumerator.GuidHexLen] = 0;
}
duk_push_array(ctx); // [DataStore][ptr][retVal]
ILibSimpleDataStore_EnumerateKeys(ds, ILibDuktape_SimpleDataStore_Keys_EnumerationSink, &enumerator);
return 1;
}
duk_ret_t ILibDuktape_SimpleDataStore_Create(duk_context *ctx)
{
ILibSimpleDataStore dataStore;
char *filePath;
duk_push_this(ctx); // [DataStore]
duk_push_object(ctx); // [DataStore][RetVal]
duk_push_current_function(ctx); // [DataStore][RetVal][func]
duk_get_prop_string(ctx, -1, "_shared"); // [DataStore][RetVal][func][shared]
if (duk_to_int(ctx, -1) != 0)
{
duk_push_heap_stash(ctx); // [DataStore][RetVal][func][shared][stash]
if (!duk_has_prop_string(ctx, -1, "_sharedDB"))
{
duk_push_null(ctx);
return 1;
}
duk_get_prop_string(ctx, -1, "_sharedDB"); // [DataStore][RetVal][func][shared][stash][sharedDB]
dataStore = (ILibSimpleDataStore)duk_to_pointer(ctx, -1);
duk_pop_n(ctx, 4); // [DataStore][RetVal]
duk_push_int(ctx, 1); // [DataStore][RetVal][shared]
duk_put_prop_string(ctx, -2, "\xFFShared"); // [DataStore][RetVal]
}
else
{
filePath = (char*)duk_require_string(ctx, 0);
dataStore = ILibSimpleDataStore_Create(filePath);
duk_pop_2(ctx); // [DataStore][RetVal]
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_SimpleDataStore_Finalizer);
}
duk_push_pointer(ctx, dataStore); // [DataStore][RetVal][ds]
duk_put_prop_string(ctx, -2, ILibDuktape_DataStore_PTR);// [DataStore][RetVal]
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);
ILibDuktape_CreateEventWithGetter(ctx, "Keys", ILibDuktape_SimpleDataStore_Keys);
return 1;
}
void ILibDuktape_SimpleDataStore_PUSH(duk_context *ctx, void *chain)
{
duk_push_object(ctx); // [DataStore]
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "_shared", 0, "Create", ILibDuktape_SimpleDataStore_Create, 1);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "_shared", 1, "Shared", ILibDuktape_SimpleDataStore_Create, 0);
}
void ILibDuktape_SimpleDataStore_init(duk_context * ctx, ILibSimpleDataStore sharedDb)
{
ILibDuktape_ModSearch_AddHandler(ctx, "SimpleDataStore", ILibDuktape_SimpleDataStore_PUSH);
if (sharedDb != NULL)
{
duk_push_heap_stash(ctx); // [stash]
duk_push_pointer(ctx, sharedDb); // [stash][ptr]
duk_put_prop_string(ctx, -2, "_sharedDB"); // [stash]
duk_pop(ctx); // ..
}
}
#ifdef __DOXY__
/*!
\brief Provides a compact Key/Value datastore. <b>Note:</b> To use, must <b>require('SimpleDataStore').Create() or require('SimpleDataStore').Shared()</b>
*/
class SimpleDataStore
{
public:
/*!
\brief Adds the specified Key/Value pair to the SimpleDataStore. If the key already exists, the old value will be overwritten.
\param key \<String\> The Key to be added to the SimpleDataStore instance. Value will be overwritten if it already exists.
\param value \<Buffer\|String\> The value to be added to the SimpleDataStore instance.
*/
void Put(key, value);
/*!
\brief Retrieves the given 'key' from the SimpleDataStore instance.
\param key \<String\> The key to retrieve from the SimpleDataStore instance
\return \<Buffer\|String\> The value bound to the specified key. NULL if the key does not exist.
*/
Object Get(key);
/*!
\brief Compacts the SimpleDataStoreInstance, removing <b>'dealloc'</b>ed blocks.
*/
void Compact();
/*!
\brief Enumerates all the keys in the SimpleDataStore instance
\return Array<String> of all the valid keys.
*/
Array<String> Keys;
/*!
\brief Creates a new SimpleDataStore instance, using the specified path
\param path \<String\> Path of the datastore to use/create.
*/
static SimpleDataStore Create(path);
/*!
\brief Creates a shared SimpleDataStore instance bound to the datastore created by the JavaScriptEngine (if available)
*/
static SimpleDataStore Shared();
};
#endif

View File

@@ -0,0 +1,27 @@
/*
Copyright 2006 - 2017 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_SIMPLEDATASTORE__
#define __DUKTAPE_SIMPLEDATASTORE__
#include "duktape.h"
#include "microstack/ILibSimpleDataStore.h"
void ILibDuktape_SimpleDataStore_init(duk_context *ctx, ILibSimpleDataStore sharedDb);
#endif

View File

@@ -0,0 +1,538 @@
/*
Copyright 2006 - 2017 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>
#endif
#include "ILibDuktape_WebRTC.h"
#include "microstack/ILibParsers.h"
#include "ILibDuktape_Helpers.h"
#include "ILibDuktapeModSearch.h"
#include "ILibDuktape_EventEmitter.h"
#include "ILibDuktape_DuplexStream.h"
#ifndef MICROSTACK_NOTLS
#include "microstack/ILibWebRTC.h"
#include "microstack/ILibWrapperWebRTC.h"
#define ILibDuktape_WebRTC_ConnectionFactoryPtr "\xFF_WebRTC_ConnectionFactoryPtr"
#define ILibDuktape_WebRTC_ConnectionPtr "\xFF_WebRTC_ConnectionPtr"
#define ILibDuktape_WebRTC_DataChannelPtr "\xFF_WebRTC_DataChannelPtr"
extern void ILibWrapper_WebRTC_ConnectionFactory_RemoveFromChain(ILibWrapper_WebRTC_ConnectionFactory factory);
typedef struct ILibWebRTC_Duktape_Handlers
{
duk_context *ctx;
void *ConnectionObject;
ILibDuktape_EventEmitter *emitter;
void *OnConnect;
void *OnDataChannel;
void *OnConnectionSendOK;
void *OnCandidate;
void *OnDisconnect;
}ILibWebRTC_Duktape_Handlers;
typedef struct ILibDuktape_WebRTC_DataChannel
{
ILibWrapper_WebRTC_DataChannel *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);
duk_ret_t ILibWebRTC_Duktape_ConnectionFactory_SetTurn(duk_context *ctx)
{
char *host = Duktape_GetStringPropertyValue(ctx, 0, "Host", NULL);
int port = Duktape_GetIntPropertyValue(ctx, 0, "Port", 3478);
duk_size_t usernameLen;
char *username = Duktape_GetStringPropertyValueEx(ctx, 0, "Username", NULL, &usernameLen);
duk_size_t passwordLen;
char *password = Duktape_GetStringPropertyValueEx(ctx, 0, "Password", "", &passwordLen);
ILibWebRTC_TURN_ConnectFlags flags = (ILibWebRTC_TURN_ConnectFlags)Duktape_GetIntPropertyValue(ctx, 0, "Mode", (int)ILibWebRTC_TURN_ENABLED);
struct sockaddr_in6* server;
ILibWrapper_WebRTC_ConnectionFactory factory;
if (host == NULL || username == NULL) { duk_push_string(ctx, "Invalid TURN Parameters"); duk_throw(ctx); return(DUK_RET_ERROR); }
server = Duktape_IPAddress4_FromString(host, (unsigned short)port);
duk_push_this(ctx);
factory = Duktape_GetPointerProperty(ctx, -1, "FactoryPtr");
ILibWrapper_WebRTC_ConnectionFactory_SetTurnServer(factory, server, username, (int)usernameLen, password, (int)passwordLen, flags);
return 0;
}
duk_idx_t ILibWebRTC_Duktape_Connection_AddRemoteCandidate(duk_context *ctx)
{
char *username;
struct sockaddr_in6 *candidate = NULL;
ILibWrapper_WebRTC_Connection connection;
duk_push_this(ctx); // [connection]
duk_get_prop_string(ctx, -1, "ConnectionPtr"); // [connection][ptr]
connection = (ILibWrapper_WebRTC_Connection*)duk_to_pointer(ctx, -1);
if (strcmp(Duktape_GetStringPropertyValue(ctx, 0, "Family", "IPv4"), "IPv4") == 0)
{
candidate = Duktape_IPAddress4_FromString(Duktape_GetStringPropertyValue(ctx, 0, "Address", "127.0.0.1"), (unsigned short)Duktape_GetIntPropertyValue(ctx, 0, "Port", 65535));
}
username = ILibWrapper_WebRTC_Connection_GetLocalUsername(connection);
ILibORTC_AddRemoteCandidate(ILibWrapper_WebRTC_Connection_GetStunModule(connection), username, candidate);
return 0;
}
/*------------------------------------------------------------------------------------------*/
ILibWrapper_WebRTC_Connection ILibDuktape_WebRTC_Native_GetConnection(duk_context *ctx)
{
ILibWrapper_WebRTC_Connection retVal = NULL;
duk_push_this(ctx); // [this]
duk_get_prop_string(ctx, -1, ILibDuktape_WebRTC_ConnectionPtr); // [this][connection]
retVal = (ILibWrapper_WebRTC_Connection)duk_get_pointer(ctx, -1);
duk_pop_2(ctx); // ...
return retVal;
}
ILibTransport_DoneState ILibDuktape_WebRTC_DataChannel_Stream_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user)
{
ILibDuktape_WebRTC_DataChannel *ptrs = (ILibDuktape_WebRTC_DataChannel*)user;
if (ptrs->dataChannel != NULL)
{
return(ILibWrapper_WebRTC_DataChannel_Send(ptrs->dataChannel, buffer, bufferLen));
}
else
{
return(ILibTransport_DoneState_ERROR);
}
}
void ILibDuktape_WebRTC_DataChannel_Stream_EndSink(ILibDuktape_DuplexStream *stream, void *user)
{
ILibDuktape_WebRTC_DataChannel *ptrs = (ILibDuktape_WebRTC_DataChannel*)user;
if (ptrs->dataChannel != NULL)
{
ILibWrapper_WebRTC_DataChannel_Close(ptrs->dataChannel);
}
}
void ILibDuktape_WebRTC_DataChannel_Stream_PauseSink(ILibDuktape_DuplexStream *sender, void *user)
{
ILibDuktape_WebRTC_DataChannel *ptrs = (ILibDuktape_WebRTC_DataChannel*)user;
if (ptrs->dataChannel != NULL)
{
void *sctpSession = ((void**)ptrs->dataChannel->parent)[0];
ILibSCTP_Pause(sctpSession);
}
}
void ILibDuktape_WebRTC_DataChannel_Stream_ResumeSink(ILibDuktape_DuplexStream *sender, void *user)
{
ILibDuktape_WebRTC_DataChannel *ptrs = (ILibDuktape_WebRTC_DataChannel*)user;
if (ptrs->dataChannel != NULL)
{
void *sctpSession = ((void**)ptrs->dataChannel->parent)[0];
ILibSCTP_Resume(sctpSession);
}
}
void ILibDuktape_WebRTC_OnDataChannelSendOK(void *dataChannel)
{
ILibDuktape_WebRTC_DataChannel *ptrs = (ILibDuktape_WebRTC_DataChannel*)((ILibWrapper_WebRTC_DataChannel*)dataChannel)->userData;
if (ptrs != NULL) { ILibDuktape_DuplexStream_Ready(ptrs->stream); }
}
void ILibDuktape_WebRTC_DataChannel_OnClose(struct ILibWrapper_WebRTC_DataChannel* dataChannel)
{
ILibDuktape_WebRTC_DataChannel *ptrs = (ILibDuktape_WebRTC_DataChannel*)dataChannel->userData;
if (ptrs != NULL)
{
ILibDuktape_DuplexStream_WriteEnd(ptrs->stream);
ptrs->dataChannel = NULL;
}
}
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); }
}
duk_ret_t ILibDuktape_WebRTC_DataChannel_Finalizer(duk_context *ctx)
{
duk_get_prop_string(ctx, 0, ILibDuktape_WebRTC_DataChannelPtr);
ILibDuktape_WebRTC_DataChannel *ptrs = (ILibDuktape_WebRTC_DataChannel*)Duktape_GetBuffer(ctx, -1, NULL);
if (ptrs->dataChannel != NULL)
{
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; }
if (dataChannel->userData != NULL) { duk_push_heapptr(((ILibDuktape_WebRTC_DataChannel*)dataChannel->userData)->ctx, ((ILibDuktape_WebRTC_DataChannel*)dataChannel->userData)->emitter->object); return; }
ILibDuktape_WebRTC_DataChannel *ptrs;
dataChannel->TransportSendOKPtr = ILibDuktape_WebRTC_OnDataChannelSendOK;
dataChannel->OnClosed = ILibDuktape_WebRTC_DataChannel_OnClose;
dataChannel->OnRawData = ILibDuktape_WebRTC_DataChannel_OnData;
duk_push_object(ctx); // [dataChannel]
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_WebRTC_DataChannel)); // [dataChannel][buffer]
ptrs = (ILibDuktape_WebRTC_DataChannel*)Duktape_GetBuffer(ctx, -1, NULL);
dataChannel->userData = ptrs;
duk_put_prop_string(ctx, -2, ILibDuktape_WebRTC_DataChannelPtr); // [dataChannel]
ptrs->dataChannel = dataChannel;
ptrs->ctx = ctx;
ptrs->emitter = ILibDuktape_EventEmitter_Create(ctx);
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_WebRTC_DataChannel_Finalizer);
duk_push_string(ctx, dataChannel->channelName);
duk_put_prop_string(ctx, -2, "name");
duk_push_int(ctx, dataChannel->streamId);
duk_put_prop_string(ctx, -2, "id");
ILibDuktape_EventEmitter_CreateEvent(ptrs->emitter, "ack", &(ptrs->OnAck));
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);
}
duk_ret_t ILibDuktape_WebRTC_ConnectionFactory_Finalizer(duk_context *ctx)
{
void *chain = Duktape_GetChain(ctx);
ILibWrapper_WebRTC_ConnectionFactory factory;
duk_get_prop_string(ctx, 0, ILibDuktape_WebRTC_ConnectionFactoryPtr);
factory = (ILibWrapper_WebRTC_ConnectionFactory)duk_get_pointer(ctx, -1);
if (factory != NULL && ILibIsChainBeingDestroyed(chain) == 0)
{
ILibWrapper_WebRTC_ConnectionFactory_RemoveFromChain(factory);
}
return 0;
}
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)
{
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); // ...
}
else if (ptrs->OnDisconnect != NULL && connected == 0)
{
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); // ...
}
}
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); // ...
}
}
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)
{
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(): "); }
duk_pop(ptrs->ctx); // ...
}
}
duk_ret_t ILibDuktape_WebRTC_generateOffer(duk_context *ctx)
{
ILibWrapper_WebRTC_Connection connection = ILibDuktape_WebRTC_Native_GetConnection(ctx);
char *offer = ILibWrapper_WebRTC_Connection_GenerateOffer(connection, ILibDuktape_WebRTC_offer_onCandidate);
if (offer != NULL)
{
duk_push_string(ctx, offer);
free(offer);
}
else
{
duk_push_null(ctx);
}
return 1;
}
duk_ret_t ILibDuktape_WebRTC_setOffer(duk_context *ctx)
{
ILibWrapper_WebRTC_Connection connection = ILibDuktape_WebRTC_Native_GetConnection(ctx);
if (!duk_is_string(ctx, 0)) { return(ILibDuktape_Error(ctx, "webrtc.connection.setOffer(): Invalid Parameter")); }
duk_size_t offerLen;
char *offer;
char *counterOffer;
offer = (char*)duk_get_lstring(ctx, 0, &offerLen);
counterOffer = ILibWrapper_WebRTC_Connection_SetOffer(connection, offer, (int)offerLen, ILibDuktape_WebRTC_offer_onCandidate);
if (counterOffer != NULL)
{
duk_push_string(ctx, counterOffer);
free(counterOffer);
}
else
{
duk_push_null(ctx);
}
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); // ...
}
}
duk_ret_t ILibDuktape_WebRTC_createDataChannel(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
ILibWrapper_WebRTC_DataChannel *retVal;
ILibWrapper_WebRTC_Connection connection = ILibDuktape_WebRTC_Native_GetConnection(ctx);
duk_size_t nameLen;
char *name;
int stream = -1;
int i;
void *OnAck = NULL;
name = (char*)duk_get_lstring(ctx, 0, &nameLen);
for (i = 1; i < nargs; ++i)
{
if (duk_is_number(ctx, i)) { stream = duk_require_int(ctx, i); }
if (duk_is_function(ctx, i)) { OnAck = duk_require_heapptr(ctx, i); }
}
if (stream < 0)
{
retVal = ILibWrapper_WebRTC_DataChannel_Create(connection, name, (int)nameLen, ILibDuktape_WebRTC_DataChannel_OnAck);
}
else
{
retVal = ILibWrapper_WebRTC_DataChannel_CreateEx(connection, name, (int)nameLen, (unsigned short)stream, ILibDuktape_WebRTC_DataChannel_OnAck);
}
ILibDuktape_WebRTC_DataChannel_PUSH(ctx, retVal);
if (OnAck != NULL)
{
ILibDuktape_EventEmitter_AddOnce(((ILibDuktape_WebRTC_DataChannel*)retVal->userData)->emitter, "ack", OnAck);
}
return 1;
}
duk_ret_t ILibDuktape_WebRTC_addRemoteCandidate(duk_context *ctx)
{
//ILibWrapper_WebRTC_Connection connection = ILibDuktape_WebRTC_Native_GetConnection(ctx);
//ILibWebRTC_Duktape_Handlers *ptrs = (ILibWebRTC_Duktape_Handlers*)ILibMemory_GetExtraMemory(connection, ILibMemory_WebRTC_Connection_CONTAINERSIZE);
return(ILibDuktape_Error(ctx, "webrtc.connection.addRemoteCandidate(): Not Supported Yet"));
}
duk_ret_t ILibDuktape_WebRTC_closeDataChannels(duk_context *ctx)
{
ILibWrapper_WebRTC_Connection connection = ILibDuktape_WebRTC_Native_GetConnection(ctx);
ILibWrapper_WebRTC_Connection_CloseAllDataChannels(connection);
return 0;
}
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);
if (connection == NULL) { return 0; }
if (ILibWrapper_WebRTC_Connection_IsConnected(connection) != 0)
{
ILibWrapper_WebRTC_Connection_CloseAllDataChannels(connection);
ILibWrapper_WebRTC_Connection_Disconnect(connection);
}
return 0;
}
duk_ret_t ILibDuktape_WebRTC_CreateConnection(duk_context *ctx)
{
ILibWebRTC_Duktape_Handlers *ptrs;
ILibWrapper_WebRTC_Connection connection;
ILibWrapper_WebRTC_ConnectionFactory factory;
duk_push_this(ctx); // [factory]
duk_get_prop_string(ctx, -1, ILibDuktape_WebRTC_ConnectionFactoryPtr);
factory = (ILibWrapper_WebRTC_ConnectionFactory)duk_get_pointer(ctx, -1);
duk_push_object(ctx); // [factory][connection]
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));
duk_push_pointer(ctx, connection); // [factory][connection][ptr]
duk_put_prop_string(ctx, -2, ILibDuktape_WebRTC_ConnectionPtr); // [factory][connection]
duk_push_int(ctx, ILibWrapper_WebRTC_Connection_GetID(connection)); // [factory][connection][id]
duk_put_prop_string(ctx, -2, "ID"); // [factory][connection]
ILibDuktape_CreateInstanceMethod(ctx, "generateOffer", ILibDuktape_WebRTC_generateOffer, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "setOffer", ILibDuktape_WebRTC_setOffer, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "createDataChannel", ILibDuktape_WebRTC_createDataChannel, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "closeDataChannels", ILibDuktape_WebRTC_closeDataChannels, 0);
ILibDuktape_CreateInstanceMethod(ctx, "addRemoteCandidate", ILibDuktape_WebRTC_addRemoteCandidate, 1);
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_WebRTC_Connection_Finalizer);
return 1;
}
void ILibDuktape_WebRTC_Push(duk_context *ctx, void *chain)
{
ILibWrapper_WebRTC_ConnectionFactory factory;
duk_push_object(ctx); // [factory]
factory = ILibWrapper_WebRTC_ConnectionFactory_CreateConnectionFactory(chain, 0);
duk_push_pointer(ctx, factory); // [factory][ptr]
duk_put_prop_string(ctx, -2, ILibDuktape_WebRTC_ConnectionFactoryPtr); // [factory]
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_WebRTC_ConnectionFactory_Finalizer);
ILibDuktape_CreateInstanceMethod(ctx, "createConnection", ILibDuktape_WebRTC_CreateConnection, 0);
}
void ILibDuktape_WebRTC_Init(duk_context * ctx)
{
ILibDuktape_ModSearch_AddHandler(ctx, "ILibWebRTC", ILibDuktape_WebRTC_Push);
Duktape_CreateEnum(ctx, "ILibWebRTC_TURN_ConnectModes", (char*[]) { "DISABLED", "ENABLED", "ALWAYS_RELAY" }, (int[]) { 0, 1, 2 }, 3);
}
#else
void ILibDuktape_WebRTC_Init(duk_context * ctx)
{
Duktape_CreateEnum(ctx, "ILibWebRTC_TURN_ConnectModes", (char*[]) { "DISABLED", "ENABLED", "ALWAYS_RELAY" }, (int[]) { 0, 1, 2 }, 3);
}
#endif
#ifdef __DOXY__
/*!
\brief WebRTC Connection Factory. <b>Note:</b> To use, must <b>require('ILibWebRTC')</b>
*/
class ILibWebRTC
{
public:
/*!
\brief Creates a new unconnected peer Connection object.
\return <Connection> Unconnected Connection
*/
static Connection createConnection();
/*!
\implements EventEmitter
\brief WebRTC Connection
*/
class Connection
{
public:
/*!
\brief Event emitted when a connection candidate is found
\param options <Object>\n
<b>host</b> Host Name or IP Address of the candidate\n
<b>port</b> Port Number of the candidate\n
*/
void candidate;
/*!
\brief Event emitted when a DataChannel is created
\param channel DataChannel
*/
void dataChannel;
/*!
\brief Event emitted when a peer connection is established
*/
void connected;
/*!
\brief Event emitted when a peer connection is severed
*/
void disconnected;
/*!
\brief Generates a WebRTC SDP Offer.
\return \<String\|NULL\> On succes, the SDP offer is returned, otherwise NULL.
*/
String generateOffer();
/*!
\brief Sets the remote WebRTC SDP Offer
\return \<String\|NULL\> On success, returns the counter WebRTC SDP offer, otherwise NULL.
*/
String setOffer(offer);
/*!
\brief Creates a WebRTC DataChannel instance
\param friendlyName \<String\> Friendly name to associate with the new DataChannel
\param streamNumber <integer> Optional. If specified, uses the desired stream number. Otherwise, one will be auto-generated.
\param callback <func> Optional. If specified, will be added as one time listener to DataChannel.ack event.
\return DataChannel instance
*/
DataChannel createDataChannel(friendlyName[, streamNumber][, callback]);
/*!
\brief Closes all DataChannel instances associated with this Connection.
*/
void closeDataChannels();
ILibDuktape_CreateInstanceMethod(ctx, "addRemoteCandidate", ILibDuktape_WebRTC_addRemoteCandidate, 1);
};
/*!
\implements EventEmitter
\implements DuplexStream
\brief WebRTC Data Channel
*/
class DataChannel
{
public:
/*!
\brief WebRTC Stream ID
*/
integer id;
/*!
\brief WebRTC DataChannel Friendly Name
*/
String name;
/*!
\brief Event emitted when the connected peer ACK's this DataChannel creation
*/
void ack;
};
};
#endif

View File

@@ -0,0 +1,8 @@
#ifndef ___ILibDuktape_WebRTC___
#define ___ILibDuktape_WebRTC___
#include "duktape.h"
void ILibDuktape_WebRTC_Init(duk_context *ctx);
#endif

View File

@@ -0,0 +1,293 @@
/*
Copyright 2006 - 2017 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 "ILibDuktape_WritableStream.h"
#include "ILibDuktape_EventEmitter.h"
#ifdef __DOXY__
/*!
\implements EventEmitter
\brief Writable streams are an abstraction for a destination to which data is written.
*/
public class WritableStream
{
public:
/*!
\brief Calling this method signals that no more data will be written to the WritableStream
*
void end([chunk][,callback])
\param chunk <Buffer | String> The optional chunk argument allows one final additional chunk of data to be written immediately before closing the stream.
\param callback If provided, the optional callback function is attached as a one time listener for the 'finish' event.
*/
void end([chunk][,callback]);
/*!
\brief This method writes some data to the stream, and calls the supplied callback once the data has been fully handled
\param chunk <Buffer | String> The data to write
\param callback If provided, the optional callback function is emitted when the data is flushed
\returns false if the calling code should wait for the 'drain' event before writing more data. true otherwise.
*/
bool write(chunk[, callback]);
/*!
\brief The 'close' event is emitted when the stream and any of its underlying resources have been closed.
*
The event indicates that no more events will be emitted, and no further computation will occur.
*/
void close;
/*!
\brief If a call to write(chunk) returns false, the 'drain' event will be emitted when it is appropriate to resume writing data to the stream.
*/
void drain;
/*!
\brief The 'error' event is emitted if an error occurred while writing or piping data.
\param arg Error argument describing the error that occured
*/
void error;
/*!
\brief The 'finish' event is emitted after the end() method has been called, and all data has been flushed to the underlying system.
*/
void finish;
/*!
\brief The 'pipe' event is emitted when the ReadableStream.pipe() method is called on a ReadableStream, adding this WriteableStream to its set of destinations.
\param src The ReadableStream that is piping to this WritableStream.
*/
void pipe;
/*!
\brief The 'unpipe' event is emitted when the unpipe() method is called on a ReadableStream, removing this WritableStream from its set of destinations.
\param src The ReadableStream that is unpiping this WritableStream.
*/
void unpipe;
};
#endif
ILibDuktape_WritableStream* ILibDuktape_WritableStream_GetStream(duk_context *ctx)
{
ILibDuktape_WritableStream* retVal;
duk_push_this(ctx); // [stream]
duk_get_prop_string(ctx, -1, ILibDuktape_WritableStream_WSPTRS); // [stream][ptr]
retVal = (ILibDuktape_WritableStream*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop_2(ctx); // ...
return retVal;
}
void ILibDuktape_WritableStream_Ready(ILibDuktape_WritableStream *stream)
{
if (stream->WaitForEnd == 0)
{
if (stream->OnWriteFlushEx != NULL)
{
// Keep it native
ILibDuktape_WriteableStream_WriteFlushNative native = stream->OnWriteFlushEx;
void *user = stream->OnWriteFlushEx_User;
stream->OnWriteFlushEx = NULL;
stream->OnWriteFlushEx_User = NULL;
native(stream, user);
}
else if (stream->OnWriteFlush != NULL)
{
duk_push_this(stream->ctx); // [stream]
duk_push_heapptr(stream->ctx, stream->OnWriteFlush); // [stream][func]
duk_swap_top(stream->ctx, -2); // [func][stream]
stream->OnWriteFlush = NULL;
duk_del_prop_string(stream->ctx, -1, "_WriteFlush");
duk_pop(stream->ctx); // [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); // ...
}
else if (stream->OnDrain != NULL)
{
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]
{
ILibDuktape_Process_UncaughtException(stream->ctx);
}
duk_pop(stream->ctx); // ...
}
}
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_ret_t ILibDuktape_WritableStream_Write(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
ILibDuktape_WritableStream *stream = ILibDuktape_WritableStream_GetStream(ctx);
duk_size_t bufferLen;
char *buffer = Duktape_GetBuffer(ctx, 0, &bufferLen);
int cbIndex = 0;
for (cbIndex = 1; cbIndex < nargs; ++cbIndex)
{
if (duk_is_function(ctx, cbIndex)) { break; }
}
if (cbIndex == nargs) { cbIndex = 0; }
if (stream->WriteSink != NULL)
{
switch (stream->WriteSink(stream, buffer, (int)bufferLen, stream->WriteSink_User))
{
case ILibTransport_DoneState_COMPLETE:
if (cbIndex != 0)
{
duk_dup(ctx, cbIndex); // [func]
duk_push_heapptr(ctx, stream->obj); // [func][this]
if (duk_pcall_method(ctx, 0) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(ctx);
}
}
duk_push_true(ctx);
break;
case ILibTransport_DoneState_INCOMPLETE:
if (cbIndex != 0)
{
stream->OnWriteFlush = duk_require_heapptr(ctx, cbIndex);
duk_push_this(ctx); // [stream]
duk_dup(ctx, cbIndex); // [stream][flush]
duk_put_prop_string(ctx, -2, "_WriteFlush"); // [stream]
}
duk_push_false(ctx);
break;
default:
if (stream->OnError != NULL)
{
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);
}
}
duk_push_false(ctx);
break;
}
}
else
{
duk_push_false(ctx);
}
return 1;
}
duk_ret_t ILibDuktape_WritableStream_End(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
ILibDuktape_WritableStream *stream = ILibDuktape_WritableStream_GetStream(ctx);
duk_size_t bufferLen;
char *buffer;
if (nargs > 0)
{
buffer = Duktape_GetBuffer(ctx, 0, &bufferLen);
if (stream->WriteSink != NULL)
{
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]
}
if (stream->WriteSink(stream, buffer, (int)bufferLen, stream->WriteSink_User) == ILibTransport_DoneState_INCOMPLETE)
{
// Incomplete, wait for SendOK
stream->WaitForEnd = 1;
}
}
}
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); }
}
return 0;
}
duk_ret_t ILibDuktape_WritableStream_End_Getter(duk_context *ctx)
{
duk_push_c_function(ctx, ILibDuktape_WritableStream_End, DUK_VARARGS);
return 1;
}
ILibDuktape_WritableStream* ILibDuktape_WritableStream_Init(duk_context *ctx, ILibDuktape_WritableStream_WriteHandler WriteHandler, ILibDuktape_WritableStream_EndHandler EndHandler, void *user)
{
ILibDuktape_WritableStream *retVal;
ILibDuktape_EventEmitter *emitter;
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_WritableStream)); // [obj][buffer]
retVal = (ILibDuktape_WritableStream*)Duktape_GetBuffer(ctx, -1, NULL); // [obj][buffer]
memset(retVal, 0, sizeof(ILibDuktape_WritableStream));
duk_put_prop_string(ctx, -2, ILibDuktape_WritableStream_WSPTRS); // [obj]
retVal->ctx = ctx;
retVal->obj = duk_get_heapptr(ctx, -1);
retVal->WriteSink = WriteHandler;
retVal->EndSink = EndHandler;
retVal->WriteSink_User = user;
emitter = ILibDuktape_EventEmitter_Create(ctx);
ILibDuktape_EventEmitter_CreateEvent(emitter, "pipe", &(retVal->OnPipe));
ILibDuktape_EventEmitter_CreateEvent(emitter, "drain", &(retVal->OnDrain));
ILibDuktape_EventEmitter_CreateEvent(emitter, "finish", &(retVal->OnFinish));
ILibDuktape_EventEmitter_CreateEvent(emitter, "error", &(retVal->OnError));
ILibDuktape_CreateInstanceMethod(ctx, "write", ILibDuktape_WritableStream_Write, DUK_VARARGS);
ILibDuktape_CreateEventWithGetter(ctx, "end", ILibDuktape_WritableStream_End_Getter);
return retVal;
}

View File

@@ -0,0 +1,55 @@
/*
Copyright 2006 - 2017 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_WRITABLESTREAM___
#define ___ILIBDUKTAPE_WRITABLESTREAM___
#include "duktape.h"
#include "microstack/ILibParsers.h"
struct ILibDuktape_WritableStream;
typedef ILibTransport_DoneState(*ILibDuktape_WritableStream_WriteHandler)(struct ILibDuktape_WritableStream *stream, char *buffer, int bufferLen, void *user);
typedef void(*ILibDuktape_WritableStream_EndHandler)(struct ILibDuktape_WritableStream *stream, void *user);
typedef void(*ILibDuktape_WriteableStream_WriteFlushNative)(struct ILibDuktape_WritableStream *stream, void *user);
typedef void(*ILibDuktape_WritableStream_PipeHandler)(struct ILibDuktape_WritableStream *stream, void *readableSource, void *user);
typedef struct ILibDuktape_WritableStream
{
duk_context *ctx;
void *obj;
void *OnDrain;
void *OnWriteFlush;
void *OnPipe;
ILibDuktape_WriteableStream_WriteFlushNative OnWriteFlushEx;
void *OnWriteFlushEx_User;
void *OnError;
void *OnFinish;
char WaitForEnd;
ILibDuktape_WritableStream_WriteHandler WriteSink;
ILibDuktape_WritableStream_EndHandler EndSink;
ILibDuktape_WritableStream_PipeHandler PipeSink;
void *WriteSink_User;
} ILibDuktape_WritableStream;
#define ILibDuktape_WritableStream_WSPTRS "\xFF_WritableStream_PTRS"
ILibDuktape_WritableStream* ILibDuktape_WritableStream_Init(duk_context *ctx, ILibDuktape_WritableStream_WriteHandler WriteHandler, ILibDuktape_WritableStream_EndHandler EndHandler, void *user);
void ILibDuktape_WritableStream_Ready(ILibDuktape_WritableStream *stream);
#endif

1443
microscript/ILibDuktape_fs.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
#ifndef ___DUKTAPE_FS___
#define ___DUKTAPE_FS___
#include "duktape.h"
void ILibDuktape_fs_init(duk_context *ctx);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,25 @@
/*
Copyright 2006 - 2017 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 ___ILIBDUKTAPEHTTP___
#define ___ILIBDUKTAPEHTTP___
#include "duktape.h"
void ILibDuktape_http_init(duk_context *ctx, void *chain);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,42 @@
/*
Copyright 2006 - 2017 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 ___ILIBDUKTAPENET___
#define ___ILIBDUKTAPENET___
#include "duktape.h"
#if defined(WINSOCK2)
#include <winsock2.h>
#include <ws2tcpip.h>
#endif
#include "microstack/ILibParsers.h"
void ILibDuktape_net_init(duk_context *ctx, void *chain);
typedef struct ILibDuktape_globalTunnel_data
{
struct sockaddr_in6 proxyServer;
ILibHashtable exceptionsTable;
char proxyUser[255];
char proxyPass[255];
}ILibDuktape_globalTunnel_data;
ILibDuktape_globalTunnel_data* ILibDuktape_GetGlobalTunnel(duk_context *ctx);
ILibDuktape_globalTunnel_data* ILibDuktape_GetNewGlobalTunnelEx(duk_context *ctx, int native);
#define ILibDuktape_GetNewGlobalTunnel(ctx) ILibDuktape_GetNewGlobalTunnelEx(ctx, 1)
#endif

View File

@@ -0,0 +1,124 @@
/*
Copyright 2006 - 2017 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>
#endif
#include "ILibWebServer_Duktape.h"
#include "microstack/ILibParsers.h"
#include "ILibParsers_Duktape.h"
#include "ILibDuktape_Helpers.h"
#include "microstack/ILibRemoteLogging.h"
#include "microstack/ILibCrypto.h"
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(_MINCORE)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif
void ILibParsers_Duktape_OnStart(void *chain, void *user)
{
duk_context *ctx = (duk_context*)((void**)user)[0];
void *OnStart = ((void**)user)[1];
duk_push_heapptr(ctx, OnStart);
if (duk_pcall(ctx, 0) != 0)
{
ILibDuktape_Process_UncaughtException(ctx);
}
duk_pop(ctx);
free(user);
}
duk_ret_t ILibParsers_Duktape_ChainOnStart(duk_context *ctx)
{
void *chain;
void *OnStart = (duk_is_undefined(ctx, 0) || duk_is_null(ctx, 0)) ? NULL : duk_require_heapptr(ctx, 0);
void **state;
duk_push_current_function(ctx);
duk_get_prop_string(ctx, -1, "chain");
chain = duk_to_pointer(ctx, -1);
if (OnStart != NULL)
{
state = (void**)ILibMemory_Allocate(2 * sizeof(void*), 0, NULL, NULL);
duk_push_heap_stash(ctx);
duk_dup(ctx, 0);
duk_put_prop_string(ctx, -2, Duktape_GetStashKey(OnStart));
state[0] = ctx;
state[1] = OnStart;
ILibChain_OnStartEvent_AddHandler(chain, ILibParsers_Duktape_OnStart, state);
ILibStartChain(chain);
}
return 0;
}
#ifdef _REMOTELOGGING
duk_ret_t ILibParsers_Duktape_StartLogger(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
void *chain;
int port = duk_require_int(ctx, 0);
int actualPort;
char *path = nargs > 1 ? (char*)duk_require_string(ctx, 1) : NULL;
duk_push_current_function(ctx);
duk_get_prop_string(ctx, -1, "chain");
chain = duk_to_pointer(ctx, -1);
actualPort = ILibStartDefaultLoggerEx(chain, port, path);
duk_push_int(ctx, actualPort);
return 1;
}
#endif
void ILibParsers_DukTape_Init(duk_context * ctx, void * chain)
{
duk_push_heap_stash(ctx); // [stash]
duk_push_pointer(ctx, chain); // [stash][chainPtr]
duk_put_prop_string(ctx, -2, "gChainPtr"); // [stash]
duk_pop(ctx); // ...
duk_push_global_object(ctx); // [g]
duk_push_c_function(ctx, ILibParsers_Duktape_ChainOnStart, 1); // [g][func]
duk_push_pointer(ctx, chain); // [g][func][chain]
duk_put_prop_string(ctx, -2, "chain"); // [g][func]
duk_put_prop_string(ctx, -2, "ILibParsers_Start"); // [g]
#ifdef _REMOTELOGGING
duk_push_c_function(ctx, ILibParsers_Duktape_StartLogger, DUK_VARARGS); // [g][func]
duk_push_pointer(ctx, chain); // [g][func][chain]
duk_put_prop_string(ctx, -2, "chain"); // [g][func]
duk_put_prop_string(ctx, -2, "ILibParsers_StartDefaultLogger"); // [g]
#endif
Duktape_CreateEnum(ctx, "RemoteLogging_Modules", (char*[]) { "UNKNOWN", "WEBRTC_ICE", "WEBRTC_DTLS", "WEBRTC_SCTP", "MESHAGENT_GUARDPOST", "MESHAGENT_P2P", "MESHAGENT_KVM", "MICROSTACK_ASYNCSOCKET", "MICROSTACK_WEB", "MICROSTACK_PIPE", "MICROSTACK_GENERIC" }, (int[]) { 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x200, 0x40, 0x80, 0x400, 0x100 }, 11);
Duktape_CreateEnum(ctx, "RemoteLogging_Flags", (char*[]) { "NONE", "DISABLE", "VERBOSITY_1", "VERBOSITY_2", "VERBOSITY_3", "VERBOSITY_4", "VERBOSITY_5" }, (int[]) { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20 }, 7);
duk_pop(ctx); // Pop Global Object
}

View File

@@ -0,0 +1,24 @@
/*
Copyright 2006 - 2017 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 ___ILIBPARSERSDUKTAPE___
#define ___ILIBPARSERSDUKTAPE___
#include "duktape.h"
void ILibParsers_DukTape_Init(duk_context *ctx, void * chain);
#endif

View File

@@ -0,0 +1,576 @@
/*
Copyright 2006 - 2017 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 "ILibWebClient_Duktape.h"
#include "microstack/ILibParsers.h"
#include "microstack/ILibWebClient.h"
#include "ILibDuktape_Helpers.h"
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(_MINCORE)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif
extern duk_idx_t ILibWebServer_DukTape_Push_PacketHeader(duk_context *ctx, ILibHTTPPacket *packet);
typedef struct ILibWebClient_DukTape_WebSocketCallbacks
{
void *OnMessage;
void *OnClose;
void *OnSendOK;
}ILibWebClient_DukTape_WebSocketCallbacks;
duk_idx_t ILibWebClient_DukTape_Push_WebRequestManager(duk_context *ctx, void* wcm);
duk_ret_t ILibWebClient_DukTape_RequestToken_Cancel(duk_context *ctx)
{
void *token;
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "TokenPtr");
token = duk_to_pointer(ctx, -1);
ILibWebClient_CancelRequest(token); //ToDo: Check to see if we should delete from stash here, or from somewhere else
return 0;
}
duk_idx_t ILibWebClient_DukTape_Push_RequestToken(duk_context *ctx, ILibWebClient_RequestToken token)
{
char *key = Duktape_GetStashKey(token);
duk_push_heap_stash(ctx);
if (duk_has_prop_string(ctx, -1, key) != 0)
{
duk_get_prop_string(ctx, -1, key); // [stash][obj]
duk_swap_top(ctx, -2); // [obj][stash]
duk_pop(ctx); // [obj]
return(duk_get_top_index(ctx));
}
duk_push_object(ctx); // [stash][obj]
duk_push_pointer(ctx, token); // [stash][obj][ptr]
duk_put_prop_string(ctx, -2, "TokenPtr"); // [stash][obj]
duk_push_c_function(ctx, ILibWebClient_DukTape_RequestToken_Cancel, 0); // [stash][obj][func]
duk_put_prop_string(ctx, -2, "Cancel"); // [stash][obj]
duk_dup(ctx, -1); // [stash][obj1][obj2]
duk_put_prop_string(ctx, -3, key); // [stash][obj2]
duk_swap_top(ctx, -2); // [obj2][stash]
duk_pop(ctx); // [obj2]
return(duk_get_top_index(ctx));
}
duk_ret_t ILibWebClient_DukTape_StateObject_Resume(duk_context *ctx)
{
return 0;
}
duk_ret_t ILibWebClient_DukTape_StateObject_Digest_NeedAuthenticate(duk_context *ctx)
{
ILibWebClient_StateObject wcdo;
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "StatePtr");
wcdo = (ILibWebClient_StateObject)duk_to_pointer(ctx, -1);
duk_push_int(ctx, ILibWebClient_Digest_NeedAuthenticate(wcdo));
return 1;
}
duk_ret_t ILibWebClient_DukTape_StateObject_Digest_GetRealm(duk_context *ctx)
{
char *realm;
ILibWebClient_StateObject wcdo;
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "StatePtr");
wcdo = (ILibWebClient_StateObject)duk_to_pointer(ctx, -1);
realm = ILibWebClient_Digest_GetRealm(wcdo);
duk_push_string(ctx, realm != NULL ? realm : "");
return 1;
}
duk_ret_t ILibWebClient_DukTape_StateObject_Digest_AddAuthenticationHeader(duk_context *ctx)
{
ILibWebClient_StateObject wcdo;
char *username;
char *password;
ILibHTTPPacket *packet;
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "StatePtr");
wcdo = (ILibWebClient_StateObject)duk_to_pointer(ctx, -1);
duk_get_prop_string(ctx, 0, "PacketPtr");
packet = (ILibHTTPPacket*)duk_to_pointer(ctx, -1);
username = (char*)duk_require_string(ctx, 1);
password = (char*)duk_require_string(ctx, 2);
ILibWebClient_GenerateAuthenticationHeader(wcdo, packet, username, password);
return 0;
}
duk_idx_t ILibWebClient_DukTape_WebClient_WebSocket_Send(duk_context *ctx)
{
int bufferType = duk_require_int(ctx, 0);
char *buffer = Duktape_GetBuffer(ctx, 1, NULL);
int bufferLen = duk_require_int(ctx, 2);
int fragmentFlags = duk_require_int(ctx, 3);
ILibWebClient_StateObject wcdo;
ILibAsyncSocket_SendStatus retVal;
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "StatePtr");
wcdo = (ILibWebClient_StateObject)duk_to_pointer(ctx, -1);
retVal = ILibWebClient_WebSocket_Send(wcdo, bufferType, buffer, bufferLen, ILibAsyncSocket_MemoryOwnership_USER, fragmentFlags);
duk_push_int(ctx, retVal);
return 1;
}
duk_idx_t ILibWebClient_DukTape_Push_StateObject(duk_context *ctx, ILibWebClient_StateObject WebStateObject)
{
char* key = Duktape_GetStashKey(WebStateObject);
duk_push_heap_stash(ctx); // [stash]
if (duk_has_prop_string(ctx, -1, key) != 0)
{
duk_get_prop_string(ctx, -1, key); // [stash][obj]
duk_swap_top(ctx, -2); // [obj][stash]
duk_pop(ctx); // [obj]
return(duk_get_top_index(ctx));
}
duk_push_object(ctx); // [stash][obj]
duk_push_pointer(ctx, WebStateObject); // [stash][obj][ptr]
duk_put_prop_string(ctx, -2, "StatePtr"); // [stash][obj]
duk_push_external_buffer(ctx); // [stash][obj][buffer]
duk_put_prop_string(ctx, -2, "BufferPtr"); // [stash][obj]
duk_push_c_function(ctx, ILibWebClient_DukTape_StateObject_Resume, 0); // [stash][obj][func]
duk_put_prop_string(ctx, -2, "Resume"); // [stash][obj]
duk_push_c_function(ctx, ILibWebClient_DukTape_StateObject_Digest_NeedAuthenticate, 0); // [stash][obj][func]
duk_put_prop_string(ctx, -2, "Digest_NeedAuthenticate"); // [stash][obj]
duk_push_c_function(ctx, ILibWebClient_DukTape_StateObject_Digest_GetRealm, 0); // [stash][obj][func]
duk_put_prop_string(ctx, -2, "Digest_GetRealm"); // [stash][obj]
duk_push_c_function(ctx, ILibWebClient_DukTape_StateObject_Digest_AddAuthenticationHeader, 3); // [stash][obj][func]
duk_put_prop_string(ctx, -2, "Digest_AddAuthenticationHeader"); // [stash][obj]
duk_push_c_function(ctx, ILibWebClient_DukTape_WebClient_WebSocket_Send, 4); // [stash][obj][func]
duk_put_prop_string(ctx, -2, "WebSocket_Send"); // [stash][obj]
duk_dup(ctx, -1); // [stash][obj][obj]
duk_put_prop_string(ctx, -3, key); // [stash][obj]
duk_swap_top(ctx, -2); // [obj][stash]
duk_pop(ctx); // [obj]
return(duk_get_top_index(ctx));
}
void ILibWebClient_DukTape_OnResponse(ILibWebClient_StateObject WebStateObject, int InterruptFlag, struct packetheader *header, char *bodyBuffer, int *beginPointer, int endPointer, ILibWebClient_ReceiveStatus recvStatus, void *user1, void *user2, int *PAUSE)
{
duk_context *ctx = (duk_context*)user1;
void *OnResp = user2;
int retVal;
duk_push_heapptr(ctx, OnResp); // [Func]
ILibWebClient_DukTape_Push_StateObject(ctx, WebStateObject); // [Func][state]
duk_push_int(ctx, InterruptFlag); // [Func][state][Interrupt]
ILibWebServer_DukTape_Push_PacketHeader(ctx, header); // [Func][state][Interrupt][header]
duk_get_prop_string(ctx, -3, "BufferPtr"); // [Func][state][Interrupt][header][buffer]
duk_config_buffer(ctx, -1, bodyBuffer + *beginPointer, endPointer - *beginPointer);
duk_push_int(ctx, endPointer - *beginPointer); // [Func][state][Interrupt][header][buffer][len]
duk_push_int(ctx, recvStatus); // [Func][state][Interrupt][header][buffer][len][status]
if (duk_pcall(ctx, 6) == 0)
{
if (duk_get_type(ctx, -1) == DUK_TYPE_UNDEFINED)
{
retVal = duk_to_int(ctx, -1);
if (retVal < 0)
{
*PAUSE = 1;
}
else
{
*beginPointer = retVal;
}
}
else
{
*beginPointer = endPointer;
}
}
else
{
ILibDuktape_Process_UncaughtException(ctx);
}
duk_pop(ctx);
if (recvStatus == ILibWebClient_ReceiveStatus_Complete)
{
// Done, so we can clear our reference in the heap stash
ILibWebClient_RequestToken token = ILibWebClient_GetRequestToken_FromStateObject(WebStateObject);
duk_push_heap_stash(ctx);
duk_del_prop_string(ctx, -1, Duktape_GetStashKey(WebStateObject));
if (token != NULL)
{
duk_del_prop_string(ctx, -1, Duktape_GetStashKey(token));
}
duk_pop(ctx);
}
}
duk_idx_t ILibWebClient_DukTape_PipelineRequest(duk_context *ctx)
{
int args = duk_get_top(ctx);
ILibHTTPPacket *packet;
char *addr;
int port;
struct sockaddr_in6* dest;
void *wcm;
ILibWebClient_OnResponse OnResp = NULL;
ILibWebClient_RequestToken token;
if (args < 3) { duk_push_string(ctx, "Too few arguments"); duk_throw(ctx); return(DUK_RET_ERROR); }
if (duk_get_prop_string(ctx, 1, "PacketPtr") == 0) { duk_push_string(ctx, "Invalid Argument[packet]"); duk_throw(ctx); return(DUK_RET_ERROR); }
packet = (ILibHTTPPacket*)duk_to_pointer(ctx, -1);
if (duk_get_prop_string(ctx, 0, "IPAddress") == 0) { duk_push_string(ctx, "Invalid Argument[RemoteEndpoint]"); duk_throw(ctx); return(DUK_RET_ERROR); }
addr = (char*)duk_to_string(ctx, -1);
if (duk_get_prop_string(ctx, 0, "Port") == 0) { duk_push_string(ctx, "Invalid Argument[RemoteEndpoint]"); duk_throw(ctx); return(DUK_RET_ERROR); }
port = duk_to_int(ctx, -1);
dest = Duktape_IPAddress4_FromString(addr, (unsigned short)port);
OnResp = duk_require_heapptr(ctx, 2);
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "ManagerPtr");
wcm = duk_to_pointer(ctx, -1);
duk_pop(ctx);
duk_dup(ctx, 2);
duk_put_prop_string(ctx, -2, "OnResponsePtr");
token = ILibWebClient_PipelineRequest(wcm, (struct sockaddr*)dest, packet, ILibWebClient_DukTape_OnResponse, ctx, OnResp);
ILibWebClient_DukTape_Push_RequestToken(ctx, token);
return 1;
}
duk_idx_t ILibWebClient_DukTape_Push_WebRequestManager(duk_context *ctx, void* wcm)
{
char* key = Duktape_GetStashKey(wcm);
duk_push_heap_stash(ctx);
if (duk_has_prop_string(ctx, -1, key))
{
duk_get_prop_string(ctx, -1, key);
}
else
{
duk_push_object(ctx);
duk_push_pointer(ctx, wcm);
duk_put_prop_string(ctx, -2, "ManagerPtr");
duk_push_c_function(ctx, ILibWebClient_DukTape_PipelineRequest, DUK_VARARGS);
duk_push_pointer(ctx, wcm);
duk_put_prop_string(ctx, -2, "ManagerPtr");
duk_put_prop_string(ctx, -2, "PipelineRequest");
}
duk_swap_top(ctx, -2); // Swap Stash and Object, so stash is on top
duk_pop(ctx); // Pop Stash off stack, leaving the object at top
return(duk_get_top_index(ctx));
}
duk_ret_t ILibWebClient_DukTape_Create(duk_context *ctx)
{
int poolSize = duk_require_int(ctx, 0);
void *chain;
ILibWebClient_RequestManager wcm;
duk_push_current_function(ctx);
duk_get_prop_string(ctx, -1, "chain");
chain = duk_to_pointer(ctx, -1);
duk_pop_2(ctx); // Pop Chain & Function
wcm = ILibCreateWebClient(poolSize, chain);
ILibWebClient_DukTape_Push_WebRequestManager(ctx, wcm);
return 1;
}
duk_ret_t ILibWebClient_DukTape_WebSocket_Finalizer(duk_context *ctx)
{
return 0;
}
duk_ret_t ILibWebClient_DukTape_WebSocket_Ptr_Setter(duk_context *ctx)
{
if (!duk_is_null(ctx, 0) && !duk_is_undefined(ctx, 0))
{
duk_push_this(ctx); // [wsock]
duk_push_current_function(ctx); // [wsock][func]
duk_get_prop_string(ctx, -1, "SetterKey"); // [wsock][func][key]
duk_swap_top(ctx, -2); // [wsock][key][func]
duk_pop(ctx); // [wsock][key]
duk_dup(ctx, 0); // [wsock][key][Ptr]
duk_put_prop(ctx, -3); // [wsock]
}
return 0;
}
void ILibWebClient_DukTape_WebSocket_OnResponse(ILibWebClient_StateObject WebStateObject, int InterruptFlag, struct packetheader *header, char *bodyBuffer, int *beginPointer, int endPointer, ILibWebClient_ReceiveStatus recvStatus, void *user1, void *user2, int *PAUSE)
{
duk_context *ctx = (duk_context*)user1;
if (header == NULL || (header->StatusCode != 101 && recvStatus == ILibWebClient_ReceiveStatus_Complete))
{
duk_push_heapptr(ctx, user2); // [wsock]
if (duk_has_prop_string(ctx, -1, "OnErrorPtr"))
{
duk_get_prop_string(ctx, -1, "OnErrorPtr"); // [wsock][OnError]
duk_swap_top(ctx, -2); // [OnError][this]
if (duk_pcall_method(ctx, 0) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(ctx);
}
duk_pop(ctx);
return;
}
duk_pop(ctx); // ...
return;
}
else if (header->StatusCode == 101)
{
ILibWebClient_DukTape_WebSocketCallbacks *callbacks = (ILibWebClient_DukTape_WebSocketCallbacks*)ILibMemory_GetExtraMemory(ILibWebClient_GetRequestToken_FromStateObject(WebStateObject), ILibMemory_WebClient_RequestToken_CONTAINERSIZE);
if (recvStatus == ILibWebClient_ReceiveStatus_Connection_Established)
{
memset(callbacks, 0, sizeof(ILibWebClient_DukTape_WebSocketCallbacks));
duk_push_heapptr(ctx, user2); // [wsock]
if (duk_has_prop_string(ctx, -1, "OnOpenPtr"))
{
duk_get_prop_string(ctx, -1, "OnMessagePtr"); // [wsock][OnMessage]
callbacks->OnMessage = duk_to_pointer(ctx, -1);
duk_pop(ctx); // [wsock]
duk_get_prop_string(ctx, -1, "OnSendOKPtr"); // [wsock][OnSendOK]
callbacks->OnSendOK = duk_to_pointer(ctx, -1);
duk_pop(ctx); // [wsock]
duk_push_pointer(ctx, WebStateObject); // [wsock][wcdo]
duk_put_prop_string(ctx, -2, "wcdo"); // [wsock]
duk_get_prop_string(ctx, -1, "OnOpenPtr"); // [wsock][OnOpen]
duk_swap_top(ctx, -2); // [OnOpen][this]
if (duk_pcall_method(ctx, 0) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(ctx);
}
}
duk_pop(ctx); // ...
}
else
{
if (callbacks->OnMessage != NULL)
{
duk_push_heapptr(ctx, callbacks->OnMessage); // [func]
duk_push_heapptr(ctx, user2); // [func][this]
duk_get_prop_string(ctx, -1, "buffer"); // [func][this][buffer]
duk_config_buffer(ctx, -1, bodyBuffer + *beginPointer, endPointer - *beginPointer);
duk_push_int(ctx, recvStatus); // [func][this][buffer][fragmentFlag]
if (duk_pcall_method(ctx, 2) == 0) // [retVal]
{
if (duk_is_number(ctx, -1))
{
*beginPointer = duk_to_int(ctx, -1);
}
else
{
*beginPointer = endPointer;
}
}
else
{
ILibDuktape_Process_UncaughtException(ctx);
}
duk_pop(ctx);
}
}
}
}
void ILibWebClient_DukTape_WebSocket_OnSendOK(ILibWebClient_StateObject wcdo, void* user1, void* user2)
{
duk_context *ctx = (duk_context*)user1;
ILibWebClient_DukTape_WebSocketCallbacks *callbacks = (ILibWebClient_DukTape_WebSocketCallbacks*)ILibMemory_GetExtraMemory(ILibWebClient_GetRequestToken_FromStateObject(wcdo), ILibMemory_WebClient_RequestToken_CONTAINERSIZE);
if (callbacks->OnSendOK != NULL)
{
duk_push_heapptr(ctx, callbacks->OnSendOK); // [func]
duk_push_heapptr(ctx, user2); // [func][this]
if (duk_pcall_method(ctx, 0) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(ctx);
}
duk_pop(ctx); // ...
}
}
duk_ret_t ILibWebClient_DukTape_W3CWebSocket_Send(duk_context *ctx)
{
char *buffer;
duk_size_t bufferLen;
ILibWebClient_WebSocket_FragmentFlags fragmentFlag = ILibWebClient_WebSocket_FragmentFlag_Complete;
ILibWebClient_WebSocket_DataTypes bufferType = duk_is_string(ctx, 0) ? ILibWebClient_WebSocket_DataType_TEXT : ILibWebClient_WebSocket_DataType_BINARY;
ILibAsyncSocket_SendStatus status;
int nargs = duk_get_top(ctx);
if (nargs < 1) { duk_push_string(ctx, "Too Few Arguments"); duk_throw(ctx); return(DUK_RET_ERROR); }
if (nargs > 1) { fragmentFlag = (ILibWebClient_WebSocket_FragmentFlags)duk_require_int(ctx, 1); }
if (duk_is_string(ctx, 0))
{
buffer = (char*)duk_get_lstring(ctx, 0, &bufferLen);
}
else
{
buffer = Duktape_GetBuffer(ctx, 0, &bufferLen);
}
duk_push_this(ctx); // [wsock]
duk_get_prop_string(ctx, -1, "wcdo"); // [wsock][wcdo]
status = ILibWebClient_WebSocket_Send(duk_to_pointer(ctx, -1), bufferType, buffer, (int)bufferLen, ILibAsyncSocket_MemoryOwnership_USER, fragmentFlag);
duk_push_int(ctx, status);
return 1;
}
duk_ret_t ILibWebClient_DukTape_WebSocketContructor(duk_context *ctx)
{
if (!duk_is_string(ctx, 0)) { return(ILibDuktape_Error(ctx, "WebSocketConstructor(): Invalid Uri")); }
duk_size_t uriLen;
char *uri = (char*)duk_get_lstring(ctx, 0, &uriLen);
char *host;
char *path;
unsigned short port;
ILibHTTPPacket *packet;
int len;
int reassemblySize = 4096;
int poolSize = 5;
void *chain;
ILibWebClient_RequestManager *wcm;
ILibWebClient_RequestToken token;
struct sockaddr_in6* dest;
if (!duk_is_constructor_call(ctx))
{
return DUK_RET_TYPE_ERROR;
}
if (duk_get_top(ctx) > 1)
{
if (duk_has_prop_string(ctx, 1, "MaxBufferSize"))
{
duk_get_prop_string(ctx, 1, "MaxBufferSize");
reassemblySize = duk_to_int(ctx, -1);
duk_pop(ctx);
}
if (duk_has_prop_string(ctx, 1, "PoolSize"))
{
duk_get_prop_string(ctx, 1, "PoolSize");
poolSize = duk_to_int(ctx, -1);
duk_pop(ctx);
}
}
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "chain"); // [func][chain]
chain = duk_to_pointer(ctx, -1);
duk_push_this(ctx); // [func][chain][wsock]
duk_swap_top(ctx, -2); // [func][wsock][chain]
duk_put_prop_string(ctx, -2, "chain"); // [func][wsock]
ILibParseUri(uri, &host, &port, &path, NULL);
packet = ILibCreateEmptyPacket();
ILibSetVersion(packet, "1.1", 3);
ILibSetDirective(packet, "GET", 3, path, (int)strnlen_s(path, (int)uriLen));
len = sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "%s:%u", host, port);
ILibAddHeaderLine(packet, "Host", 4, ILibScratchPad, len);
ILibWebClient_AddWebSocketRequestHeaders(packet, reassemblySize, ILibWebClient_DukTape_WebSocket_OnSendOK);
duk_push_heap_stash(ctx); // [heapstash]
if (duk_has_prop_string(ctx, -1, "WSockClient"))
{
duk_get_prop_string(ctx, -1, "WSockClient"); // [heapstash][wcm]
wcm = (ILibWebClient_RequestManager)duk_to_pointer(ctx, -1);
duk_pop_2(ctx); // ...
}
else
{
wcm = ILibCreateWebClient(poolSize, chain);
duk_push_pointer(ctx, wcm); // [heapstash][wcm]
duk_put_prop_string(ctx, -2, "WSockClient"); // [heapstash]
}
duk_pop(ctx); // [func][wsock]
duk_push_c_function(ctx, ILibWebClient_DukTape_WebSocket_Finalizer, 1); // [func][wsock][fin]
duk_set_finalizer(ctx, -2); // [func][wsock]
duk_push_external_buffer(ctx); // [func][wsock][buffer]
duk_put_prop_string(ctx, -2, "buffer"); // [func][wsock]
duk_push_string(ctx, "onopen"); // [func][wsock][key]
duk_push_c_function(ctx, ILibWebClient_DukTape_WebSocket_Ptr_Setter, 1); // [func][wsock][key][func]
duk_push_string(ctx, "OnOpenPtr"); // [func][wsock][key][func][str]
duk_put_prop_string(ctx, -2, "SetterKey"); // [func][wsock][key][func]
duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_SETTER); // [func][wsock]
duk_push_string(ctx, "onmessage"); // [func][wsock][key]
duk_push_c_function(ctx, ILibWebClient_DukTape_WebSocket_Ptr_Setter, 1); // [func][wsock][key][func]
duk_push_string(ctx, "OnMessagePtr"); // [func][wsock][key][func][str]
duk_put_prop_string(ctx, -2, "SetterKey"); // [func][wsock][key][func]
duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_SETTER); // [func][wsock]
duk_push_string(ctx, "onerror"); // [func][wsock][key]
duk_push_c_function(ctx, ILibWebClient_DukTape_WebSocket_Ptr_Setter, 1); // [func][wsock][key][func]
duk_push_string(ctx, "OnErrorPtr"); // [func][wsock][key][func][str]
duk_put_prop_string(ctx, -2, "SetterKey"); // [func][wsock][key][func]
duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_SETTER); // [func][wsock]
duk_push_string(ctx, "onclose"); // [func][wsock][key]
duk_push_c_function(ctx, ILibWebClient_DukTape_WebSocket_Ptr_Setter, 1); // [func][wsock][key][func]
duk_push_string(ctx, "OnClosePtr"); // [func][wsock][key][func][str]
duk_put_prop_string(ctx, -2, "SetterKey"); // [func][wsock][key][func]
duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_SETTER); // [func][wsock]
duk_push_string(ctx, "onsendok"); // [func][wsock][key]
duk_push_c_function(ctx, ILibWebClient_DukTape_WebSocket_Ptr_Setter, 1); // [func][wsock][key][func]
duk_push_string(ctx, "OnSendOKPtr"); // [func][wsock][key][func][str]
duk_put_prop_string(ctx, -2, "SetterKey"); // [func][wsock][key][func]
duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_SETTER); // [func][wsock]
duk_push_c_function(ctx, ILibWebClient_DukTape_W3CWebSocket_Send, DUK_VARARGS); // [func][wsock][func]
duk_put_prop_string(ctx, -2, "Send"); // [func][wsock]
dest = Duktape_IPAddress4_FromString(host, port);
token = ILibWebClient_PipelineRequest(wcm, (struct sockaddr*)dest, packet, ILibWebClient_DukTape_WebSocket_OnResponse, ctx, duk_get_heapptr(ctx, -1));
duk_push_pointer(ctx, token); // [func][wsock][token]
duk_put_prop_string(ctx, -2, "RequestTokenPtr");// [func][wsock]
return 0;
}
void ILibWebClient_DukTape_Init(duk_context * ctx, void * chain)
{
duk_push_global_object(ctx);
duk_push_c_function(ctx, ILibWebClient_DukTape_Create, 1); // [global][func]
duk_push_pointer(ctx, chain); // [global][func][chain]
duk_put_prop_string(ctx, -2, "chain"); // [global][func]
duk_put_prop_string(ctx, -2, "ILibWebClient_Create"); // [global]
duk_push_c_function(ctx, ILibWebClient_DukTape_WebSocketContructor, DUK_VARARGS); // [global][func]
duk_push_pointer(ctx, chain); // [global][func][chain]
duk_put_prop_string(ctx, -2, "chain"); // [global][func]
duk_put_prop_string(ctx, -2, "WebSocket"); // [global]
Duktape_CreateEnum(ctx, "WebSocket_Status", (char*[]) { "COMPLETE_FRAGMENT", "END", "PARTIAL_FRAGMENT", "LAST_PARTIAL_FRAGMENT" }, (int[]) { 0, 1, 10, 11 }, 4);
duk_pop(ctx);
}

View File

@@ -0,0 +1,25 @@
/*
Copyright 2006 - 2017 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 ___ILIBWEBCLIENTDUKTAPE___
#define ___ILIBWEBCLIENTDUKTAPE___
#include "duktape.h"
void ILibWebClient_DukTape_Init(duk_context *ctx, void * chain);
#endif

View File

@@ -0,0 +1,717 @@
/*
Copyright 2006 - 2017 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 "ILibWebServer_Duktape.h"
#include "ILibDuktapeModSearch.h"
#include "microstack/ILibParsers.h"
#include "microstack/ILibWebServer.h"
#include "microstack/ILibWebClient.h"
#include "ILibDuktape_Helpers.h"
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(_MINCORE)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif
duk_idx_t ILibWebServer_DukTape_Push_ILibWebServerSession(duk_context *ctx, ILibWebServer_Session *session);
duk_idx_t ILibWebServer_DukTape_Push_PacketHeader(duk_context *ctx, ILibHTTPPacket *packet);
void ILibWebServer_DukTape_PUSH_IncomingMessage(duk_context *ctx, ILibHTTPPacket *packet, ILibWebServer_Session *session);
void ILibWebServer_DukTape_PUSH_ServerResponse(duk_context *ctx, ILibWebServer_Session *session);
void* Duktape_GetSessionPtr(duk_context *ctx)
{
void *retVal;
duk_push_this(ctx); // [session]
duk_get_prop_string(ctx, -1, "SessionPtr"); // [session][ptr]
retVal = duk_to_pointer(ctx, -1);
duk_pop_2(ctx); // ...
return retVal;
}
duk_ret_t ILibWebServer_DukTape_SendResponse(duk_context *ctx)
{
ILibWebServer_Session *session;
ILibHTTPPacket *packet;
int retVal;
duk_get_prop_string(ctx, 0, "PacketPtr");
packet = (ILibHTTPPacket*)duk_to_pointer(ctx, -1);
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "SessionPtr");
session = (ILibWebServer_Session*)duk_to_pointer(ctx, -1);
retVal = (int)ILibWebServer_Send(session, packet);
duk_push_int(ctx, retVal);
return 1;
}
duk_ret_t ILibWebServer_DukTape_SendResponseRaw(duk_context *ctx)
{
ILibWebServer_Session *session;
char* buffer;
int bufferLen;
int retVal;
int doneFlag;
bufferLen = duk_require_int(ctx, 1);
buffer = Duktape_GetBuffer(ctx, 0, NULL);
doneFlag = duk_require_int(ctx, 2);
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "SessionPtr");
session = (ILibWebServer_Session*)duk_to_pointer(ctx, -1);
retVal = (int)ILibWebServer_Send_Raw(session, buffer, bufferLen, ILibAsyncSocket_MemoryOwnership_USER, (ILibWebServer_DoneFlag)doneFlag);
duk_push_int(ctx, retVal);
return 1;
}
duk_ret_t ILibWebServer_DukTape_Session_StreamHeader(duk_context *ctx)
{
// enum ILibWebServer_Status ILibWebServer_StreamHeader(struct ILibWebServer_Session *session, struct packetheader *header);
ILibWebServer_Session *session;
ILibHTTPPacket *packet;
int retVal;
duk_get_prop_string(ctx, 0, "PacketPtr");
packet = (ILibHTTPPacket*)duk_to_pointer(ctx, -1);
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "SessionPtr");
session = (ILibWebServer_Session*)duk_to_pointer(ctx, -1);
retVal = (int)ILibWebServer_StreamHeader(session, packet);
duk_push_int(ctx, retVal);
return 1;
}
duk_ret_t ILibWebServer_DukTape_Session_StreamHeaderRaw(duk_context *ctx)
{
// enum ILibWebServer_Status ILibWebServer_StreamHeader_Raw(struct ILibWebServer_Session *session, int StatusCode, char *StatusData, char *ResponseHeaders, enum ILibAsyncSocket_MemoryOwnership ResponseHeaders_FREE)
ILibWebServer_Session *session;
int responseCode;
char *statusData;
char *responseHeaders;
int retVal;
responseCode = duk_require_int(ctx, 0);
statusData = (char*)duk_require_string(ctx, 1);
responseHeaders = (char*)duk_require_string(ctx, 2);
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "SessionPtr");
session = (ILibWebServer_Session*)duk_to_pointer(ctx, -1);
retVal = ILibWebServer_StreamHeader_Raw(session, responseCode, statusData, responseHeaders, ILibAsyncSocket_MemoryOwnership_USER);
duk_push_int(ctx, retVal);
return 1;
}
duk_ret_t ILibWebServer_DukTape_Session_StreamBody(duk_context *ctx)
{
// enum ILibWebServer_Status ILibWebServer_StreamBody(struct ILibWebServer_Session *session, char *buffer, int bufferSize, enum ILibAsyncSocket_MemoryOwnership userFree, ILibWebServer_DoneFlag done);
ILibWebServer_Session *session;
char *body;
int bodyLen;
int doneFlag;
int retVal;
bodyLen = duk_require_int(ctx, 1);
doneFlag = duk_require_int(ctx, 2);
body = Duktape_GetBuffer(ctx, 0, NULL);
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "SessionPtr");
session = (ILibWebServer_Session*)duk_to_pointer(ctx, -1);
retVal = (int)ILibWebServer_StreamBody(session, body, bodyLen, ILibAsyncSocket_MemoryOwnership_USER, (ILibWebServer_DoneFlag)doneFlag);
duk_push_int(ctx, retVal);
return 1;
}
duk_ret_t ILibWebServer_DukTape_Session_Digest_IsAuthenticated(duk_context *ctx)
{
// ILibWebServer_Digest_IsAuthenticated
if (!duk_is_string(ctx, 0)) { return(ILibDuktape_Error(ctx, "IsAuthenticated(): Invalid Parameter/Type")); }
ILibWebServer_Session *session;
duk_size_t realmLen;
char* realm = (char*)duk_get_lstring(ctx, 0, &realmLen);
int retVal;
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "SessionPtr");
session = (ILibWebServer_Session*)duk_to_pointer(ctx, -1);
retVal = (int)ILibWebServer_Digest_IsAuthenticated(session, realm, (int)realmLen);
duk_push_int(ctx, retVal);
return 1;
}
duk_ret_t ILibWebServer_DukTape_Session_Digest_SendUnauthorized(duk_context *ctx)
{
// void ILibWebServer_Digest_SendUnauthorized(struct ILibWebServer_Session *session, char* realm, int realmLen, char* html, int htmllen);
ILibWebServer_Session *session;
if (!duk_is_string(ctx, 0)) { return(ILibDuktape_Error(ctx, "SendUnAuthorized(): Invalid Parameter/Type (realm)")); }
duk_size_t realmLen;
char *realm = (char*)duk_get_lstring(ctx, 0, &realmLen);
int htmlLen = duk_require_int(ctx, 2);
char *html = Duktape_GetBuffer(ctx, 1, NULL);
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "SessionPtr");
session = (ILibWebServer_Session*)duk_to_pointer(ctx, -1);
ILibWebServer_Digest_SendUnauthorized(session, realm, (int)realmLen, html, htmlLen);
return 0;
}
duk_ret_t ILibWebServer_DukTape_Session_Digest_GetUsername(duk_context *ctx)
{
ILibWebServer_Session *session;
char *username;
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "SessionPtr");
session = (ILibWebServer_Session*)duk_to_pointer(ctx, -1);
username = ILibWebServer_Digest_GetUsername(session);
duk_push_string(ctx, username != NULL ? username : "");
return 1;
}
duk_ret_t ILibWebServer_DukTape_Session_Digest_ValidatePassword(duk_context *ctx)
{
// int ILibWebServer_Digest_ValidatePassword(struct ILibWebServer_Session *session, char* password, int passwordLen);
ILibWebServer_Session *session;
int passwordLen = duk_require_int(ctx, 1);
char *password = Duktape_GetBuffer(ctx, 0, NULL);
int retVal;
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "SessionPtr");
session = (ILibWebServer_Session*)duk_to_pointer(ctx, -1);
retVal = ILibWebServer_Digest_ValidatePassword(session, password, passwordLen);
duk_push_int(ctx, retVal);
return 1;
}
void ILibWebServer_DukTape_Session_OnReceive(struct ILibWebServer_Session *sender, int InterruptFlag, struct packetheader *header, char *bodyBuffer, int *beginPointer, int endPointer, ILibWebServer_DoneFlag done)
{
duk_context *ctx = (duk_context*)((void**)sender->ParentExtraMemory)[0];
void* OnReceive = ((void**)sender->Reserved_Transport.ChainLink.ExtraMemoryPtr)[0];
duk_push_heapptr(ctx, OnReceive);
ILibWebServer_DukTape_Push_ILibWebServerSession(ctx, sender);
ILibWebServer_DukTape_Push_PacketHeader(ctx, header); // [func][this][header]
duk_get_prop_string(ctx, -2, "buffer"); // [func][this][header][buffer]
duk_config_buffer(ctx, -1, bodyBuffer + *beginPointer, endPointer - *beginPointer);
duk_push_int(ctx, (int)done); // [func][this][header][buffer][done]
if (duk_pcall_method(ctx, 3) == 0) // [retVal]
{
if (duk_get_type(ctx, -1) == DUK_TYPE_NUMBER)
{
*beginPointer = duk_get_int(ctx, -1);
}
else
{
*beginPointer = endPointer;
}
}
else
{
ILibDuktape_Process_UncaughtException(ctx);
}
duk_pop(ctx);
}
void ILibWebServer_DukTape_Session_OnDisconnect(struct ILibWebServer_Session *sender)
{
duk_context *ctx = (duk_context*)((void**)sender->ParentExtraMemory)[0];
void* OnDisconnect = ((void**)sender->Reserved_Transport.ChainLink.ExtraMemoryPtr)[1];
duk_push_heapptr(ctx, OnDisconnect);
ILibWebServer_DukTape_Push_ILibWebServerSession(ctx, sender);
if (duk_pcall_method(ctx, 0) != 0)
{
ILibDuktape_Process_UncaughtException(ctx);
}
duk_pop(ctx);
}
void ILibWebServer_DukTape_Session_OnSendOk(struct ILibWebServer_Session *sender)
{
duk_context *ctx = (duk_context*)((void**)sender->ParentExtraMemory)[0];
void* OnSendOK = ((void**)sender->Reserved_Transport.ChainLink.ExtraMemoryPtr)[2];
duk_push_heapptr(ctx, OnSendOK); // [func]
ILibWebServer_DukTape_Push_ILibWebServerSession(ctx, sender); // [func][this]
if (duk_pcall_method(ctx, 0) != 0)
{
ILibDuktape_Process_UncaughtException(ctx);
}
duk_pop(ctx);
}
duk_ret_t ILibWebServer_DukTape_OnReceive_Setter(duk_context *ctx)
{
void *OnReceive = duk_require_heapptr(ctx, 0);
ILibWebServer_Session *session;
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "SessionPtr");
session = (ILibWebServer_Session*)duk_to_pointer(ctx, -1);
((void**)session->Reserved_Transport.ChainLink.ExtraMemoryPtr)[0] = OnReceive;
session->OnReceive = ILibWebServer_DukTape_Session_OnReceive;
duk_push_heapptr(ctx, session->User); // [session]
duk_dup(ctx, 0); // [session][ptr]
duk_put_prop_string(ctx, -2, "OnReceivePtr"); // [session]
return 0;
}
duk_ret_t ILibWebServer_DukTape_OnDisconnect_Setter(duk_context *ctx)
{
void *OnDisconnect = duk_require_heapptr(ctx, 0);
ILibWebServer_Session *session;
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "SessionPtr");
session = (ILibWebServer_Session*)duk_to_pointer(ctx, -1);
((void**)session->Reserved_Transport.ChainLink.ExtraMemoryPtr)[1] = OnDisconnect;
session->OnDisconnect = ILibWebServer_DukTape_Session_OnDisconnect;
duk_push_heapptr(ctx, session->User); // [session]
duk_dup(ctx, 0); // [session][ptr]
duk_put_prop_string(ctx, -2, "OnDisconnectPtr"); // [session]
return 0;
}
duk_ret_t ILibWebServer_DukTape_OnSendOk_Setter(duk_context *ctx)
{
void *OnSendOk = duk_require_heapptr(ctx, 0);
ILibWebServer_Session *session;
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "SessionPtr");
session = (ILibWebServer_Session*)duk_to_pointer(ctx, -1);
((void**)session->Reserved_Transport.ChainLink.ExtraMemoryPtr)[2] = OnSendOk;
session->OnSendOK = ILibWebServer_DukTape_Session_OnSendOk;
duk_push_heapptr(ctx, session->User); // [session]
duk_dup(ctx, 0); // [session][ptr]
duk_put_prop_string(ctx, -2, "OnSendOKPtr"); // [session]
return 0;
}
duk_idx_t ILibWebServer_DukTape_Session_IsCrossSiteRequest(duk_context *ctx)
{
ILibWebServer_Session *session;
char *retVal;
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "SessionPtr");
session = (ILibWebServer_Session*)duk_to_pointer(ctx, -1);
retVal = ILibWebServer_IsCrossSiteRequest(session);
duk_push_string(ctx, retVal == NULL ? "" : retVal);
return 1;
}
duk_idx_t ILibWebServer_DukTape_Session_GetWebSocketDataType(duk_context *ctx)
{
ILibWebServer_Session *session;
ILibWebServer_WebSocket_DataTypes retVal;
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "SessionPtr");
session = (ILibWebServer_Session*)duk_to_pointer(ctx, -1);
retVal = ILibWebServer_WebSocket_GetDataType(session);
duk_push_int(ctx, (int)retVal);
return 1;
}
duk_idx_t ILibWebServer_DukTape_Session_UpgradeWebSocket(duk_context *ctx)
{
ILibWebServer_Session *session = Duktape_GetSessionPtr(ctx);
int fragmentReassemblySize = duk_require_int(ctx, 0);
int retVal;
retVal = ILibWebServer_UpgradeWebSocket(session, fragmentReassemblySize);
duk_push_int(ctx, retVal);
return 1;
}
duk_idx_t ILibWebServer_DukTape_Session_WebSocket_Send(duk_context *ctx)
{
// enum ILibWebServer_Status ILibWebServer_WebSocket_Send(struct ILibWebServer_Session *session, char* buffer, int bufferLen, ILibWebServer_WebSocket_DataTypes bufferType, enum ILibAsyncSocket_MemoryOwnership userFree, ILibWebServer_WebSocket_FragmentFlags fragmentStatus);
ILibWebServer_Session *session = Duktape_GetSessionPtr(ctx);
char *buffer = Duktape_GetBuffer(ctx, 0, NULL);
int bufferLen = duk_require_int(ctx, 1);
int dataType = duk_require_int(ctx, 2);
int fragmentFlags = duk_require_int(ctx, 3);
ILibWebServer_Status retVal = ILibWebServer_WebSocket_Send(session, buffer, bufferLen, dataType, ILibAsyncSocket_MemoryOwnership_USER, fragmentFlags);
duk_push_int(ctx, (int)retVal);
return 1;
}
duk_idx_t ILibWebServer_DukTape_Session_WebSocket_Close(duk_context *ctx)
{
ILibWebServer_Session *session = Duktape_GetSessionPtr(ctx);
ILibWebServer_WebSocket_Close(session);
return 0;
}
duk_ret_t ILibWebServer_DukTape_Session_Pause(duk_context *ctx)
{
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "SessionPtr");
ILibWebServer_Pause((ILibWebServer_Session*)duk_to_pointer(ctx, -1));
return 0;
}
duk_ret_t ILibWebServer_DukTape_Session_Resume(duk_context *ctx)
{
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "SessionPtr");
ILibWebServer_Resume((ILibWebServer_Session*)duk_to_pointer(ctx, -1));
return 0;
}
duk_idx_t ILibWebServer_DukTape_Push_ILibWebServerSession(duk_context *ctx, ILibWebServer_Session *session)
{
if (session->User != NULL)
{
duk_push_heapptr(ctx, session->User); // [session]
return(duk_get_top_index(ctx));
}
duk_push_heap_stash(ctx); // [stash]
duk_push_object(ctx); // [stash][obj]
session->User = duk_get_heapptr(ctx, -1);
duk_dup(ctx, -1); // [stash][obj][obj]
duk_put_prop_string(ctx, -3, Duktape_GetStashKey(session->User)); // [stash][obj]
duk_swap_top(ctx, -2); // [obj][stash]
duk_pop(ctx); // [obj]
duk_push_external_buffer(ctx); // [obj][buffer]
duk_put_prop_string(ctx, -2, "buffer"); // [obj]
duk_push_pointer(ctx, session); // [obj][pointer]
duk_put_prop_string(ctx, -2, "SessionPtr"); // [obj]
duk_push_c_function(ctx, ILibWebServer_DukTape_SendResponse, 1); // [obj][func]
duk_put_prop_string(ctx, -2, "SendResponse"); // [obj]
duk_push_c_function(ctx, ILibWebServer_DukTape_SendResponseRaw, 3);
duk_put_prop_string(ctx, -2, "SendResponseRaw");
duk_push_c_function(ctx, ILibWebServer_DukTape_Session_StreamHeader, 1);
duk_put_prop_string(ctx, -2, "StreamHeader");
duk_push_c_function(ctx, ILibWebServer_DukTape_Session_StreamHeaderRaw, 3);
duk_put_prop_string(ctx, -2, "StreamHeaderRaw");
duk_push_c_function(ctx, ILibWebServer_DukTape_Session_StreamBody, 3);
duk_put_prop_string(ctx, -2, "StreamBody");
duk_push_c_function(ctx, ILibWebServer_DukTape_Session_Pause, 0);
duk_put_prop_string(ctx, -2, "Pause");
duk_push_c_function(ctx, ILibWebServer_DukTape_Session_Resume, 0);
duk_put_prop_string(ctx, -2, "Resume");
duk_push_c_function(ctx, ILibWebServer_DukTape_Session_Digest_IsAuthenticated, 1);
duk_put_prop_string(ctx, -2, "Digest_IsAuthenticated");
duk_push_c_function(ctx, ILibWebServer_DukTape_Session_Digest_SendUnauthorized, 3);
duk_put_prop_string(ctx, -2, "Digest_SendUnauthorized");
duk_push_c_function(ctx, ILibWebServer_DukTape_Session_Digest_GetUsername, 0);
duk_put_prop_string(ctx, -2, "Digest_GetUsername");
duk_push_c_function(ctx, ILibWebServer_DukTape_Session_Digest_ValidatePassword, 2);
duk_put_prop_string(ctx, -2, "Digest_ValidatePassword");
duk_push_c_function(ctx, ILibWebServer_DukTape_Session_IsCrossSiteRequest, 0);
duk_put_prop_string(ctx, -2, "IsCrossSiteRequest");
duk_push_c_function(ctx, ILibWebServer_DukTape_Session_GetWebSocketDataType, 0);
duk_put_prop_string(ctx, -2, "WebSocket_GetDataType");
duk_push_c_function(ctx, ILibWebServer_DukTape_Session_UpgradeWebSocket, 1);
duk_put_prop_string(ctx, -2, "WebSocket_UpgradeToWebSocket");
duk_push_c_function(ctx, ILibWebServer_DukTape_Session_WebSocket_Send, 4);
duk_put_prop_string(ctx, -2, "WebSocket_Send");
duk_push_c_function(ctx, ILibWebServer_DukTape_Session_WebSocket_Close, 0);
duk_put_prop_string(ctx, -2, "WebSocket_Close");
duk_push_string(ctx, "OnReceive"); //[obj][key]
duk_push_c_function(ctx, ILibWebServer_DukTape_OnReceive_Setter, 1); //[obj][key][Func]
duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_SETTER); //[obj]
duk_push_string(ctx, "OnDisconnect"); //[obj][key]
duk_push_c_function(ctx, ILibWebServer_DukTape_OnDisconnect_Setter, 1); //[obj][key][Func]
duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_SETTER); //[obj]
duk_push_string(ctx, "OnSendOk"); //[obj][key]
duk_push_c_function(ctx, ILibWebServer_DukTape_OnSendOk_Setter, 1); //[obj][key][Func]
duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_SETTER); //[obj]
return duk_get_top_index(ctx);
}
duk_ret_t ILibWebServer_DukTape_GetHeaderline(duk_context *ctx)
{
if (!duk_is_string(ctx, 0)) { return(ILibDuktape_Error(ctx, "GetHeaderLine(): Invalid Parameter/Type")); }
duk_size_t headerLen;
char* header = (char*)duk_get_lstring(ctx, 0, &headerLen);
struct packetheader *packet;
char* val;
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "PacketPtr");
packet = (struct packetheader*)duk_to_pointer(ctx, -1);
val = ILibGetHeaderLine(packet, header, (int)headerLen);
if (val == NULL)
{
duk_push_string(ctx, "");
}
else
{
duk_push_string(ctx, val);
}
return 1;
}
duk_ret_t ILibWebServer_DukTape_Packet_SetDirective(duk_context *ctx)
{
if (!duk_is_string(ctx, 0) || !duk_is_string(ctx, 1)) { return(ILibDuktape_Error(ctx, "SetDirective(): Invalid Parameter/Type(s)")); }
duk_size_t directiveLen, pathLen;
char *directive = (char*)duk_get_lstring(ctx, 0, &directiveLen);
char *path = (char*)duk_get_lstring(ctx, 1, &pathLen);
struct packetheader *packet;
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "PacketPtr");
packet = (struct packetheader*)duk_to_pointer(ctx, -1);
ILibSetDirective(packet, directive, (int)directiveLen, path, (int)pathLen);
return 0;
}
duk_ret_t ILibWebServer_DukTape_Packet_AddHeader(duk_context *ctx)
{
if (!duk_is_string(ctx, 0) || !duk_is_string(ctx, 1)) { return(ILibDuktape_Error(ctx, "AddHeader(): Invalid Parameter/Type(s)")); }
duk_size_t fieldNameLen, fieldNameValueLen;
char* fieldName = (char*)duk_get_lstring(ctx, 0, &fieldNameLen);
char* fieldValue = (char*)duk_get_lstring(ctx, 1, &fieldNameValueLen);
struct packetheader *packet;
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "PacketPtr");
packet = (struct packetheader*)duk_to_pointer(ctx, -1);
ILibAddHeaderLine(packet, fieldName, (int)fieldNameLen, fieldValue, (int)fieldNameValueLen);
return 0;
}
duk_ret_t ILibWebServer_DukTape_Packet_SetResponse(duk_context *ctx)
{
int statusCode = duk_require_int(ctx, 0);
duk_size_t responseLen;
if (!duk_is_string(ctx, 1)) { return(ILibDuktape_Error(ctx, "SetResponse(): Response was invalid ParameterType")); }
char *response = (char*)duk_get_lstring(ctx, 1, &responseLen);
struct packetheader *packet;
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "PacketPtr");
packet = (struct packetheader*)duk_to_pointer(ctx, -1);
ILibSetStatusCode(packet, statusCode, response, (int)responseLen);
return 0;
}
duk_ret_t ILibWebServer_DukTape_Packet_SetStringBody(duk_context *ctx)
{
duk_size_t bodyLen;
if (!duk_is_string(ctx, 0)) { return(ILibDuktape_Error(ctx, "SetStringBody(): Invalid Parameter/Type")); }
char *body = (char*)duk_get_lstring(ctx, 0, &bodyLen);
struct packetheader *packet;
char *tmp;
char len[65];
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "PacketPtr");
packet = (struct packetheader*)duk_to_pointer(ctx, -1);
tmp = ILibString_Copy(body, (int)bodyLen);
packet->Body = tmp;
packet->BodyLength = (int)bodyLen;
#ifdef WIN32
_itoa_s(packet->BodyLength, len, 65, 10);
#else
sprintf_s(len, 65, "%d", packet->BodyLength);
#endif
ILibAddHeaderLine(packet, "Content-Length", 14, len, (int)strnlen_s(len, sizeof(len)));
return 0;
}
duk_ret_t ILibWebServer_DukTape_Packet_SetBody(duk_context *ctx)
{
int bodyLen = duk_require_int(ctx, 1);
char len[65];
struct packetheader *packet;
char* body;
body = Duktape_GetBuffer(ctx, 0, NULL);
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "PacketPtr");
packet = (struct packetheader*)duk_to_pointer(ctx, -1);
packet->Body = (char*)malloc(bodyLen);
memcpy_s(packet->Body, bodyLen, body, bodyLen);
packet->BodyLength = bodyLen;
#ifdef WIN32
_itoa_s(packet->BodyLength, len, 65, 10);
#else
sprintf_s(len, 65, "%d", packet->BodyLength);
#endif
ILibAddHeaderLine(packet, "Content-Length", 14, len, (int)strnlen_s(len, sizeof(len)));
return 0;
}
duk_idx_t ILibWebServer_DukTape_PacketHeader_AddWebSocketRequestHeaders(duk_context *ctx)
{
ILibHTTPPacket *packet;
int maxReassemblySize = duk_require_int(ctx, 0);
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "PacketPtr");
packet = (ILibHTTPPacket*)duk_to_pointer(ctx, -1);
ILibWebClient_AddWebSocketRequestHeaders(packet, maxReassemblySize, NULL);
return 0;
}
duk_idx_t ILibWebServer_DukTape_Push_PacketHeader(duk_context *ctx, ILibHTTPPacket *packet)
{
duk_idx_t j;
j = duk_push_object(ctx);
duk_push_pointer(ctx, packet);
duk_put_prop_string(ctx, j, "PacketPtr");
if (packet->Directive != NULL)
{
packet->Directive[packet->DirectiveLength] = 0;
duk_push_string(ctx, packet->Directive);
duk_put_prop_string(ctx, j, "Directive");
packet->DirectiveObj[packet->DirectiveObjLength] = 0;
duk_push_string(ctx, packet->DirectiveObj);
duk_put_prop_string(ctx, j, "Path");
}
if(packet->StatusData != NULL)
{
duk_push_int(ctx, packet->StatusCode);
duk_put_prop_string(ctx, j, "StatusCode");
packet->StatusData[packet->StatusDataLength] = 0;
duk_push_string(ctx, packet->StatusData);
duk_put_prop_string(ctx, j, "StatusData");
}
duk_push_c_function(ctx, ILibWebServer_DukTape_PacketHeader_AddWebSocketRequestHeaders, 1);
duk_put_prop_string(ctx, j, "WebSocket_AddRequestHeaders");
duk_push_c_function(ctx, ILibWebServer_DukTape_GetHeaderline, 1);
duk_put_prop_string(ctx, j, "GetHeader");
duk_push_c_function(ctx, ILibWebServer_DukTape_Packet_AddHeader, 2);
duk_put_prop_string(ctx, j, "AddHeader");
duk_push_c_function(ctx, ILibWebServer_DukTape_Packet_SetDirective, 2);
duk_put_prop_string(ctx, j, "SetDirective");
duk_push_c_function(ctx, ILibWebServer_DukTape_Packet_SetResponse, 2);
duk_put_prop_string(ctx, j, "SetResponse");
duk_push_c_function(ctx, ILibWebServer_DukTape_Packet_SetStringBody, 1);
duk_put_prop_string(ctx, j, "SetStringBody");
duk_push_c_function(ctx, ILibWebServer_DukTape_Packet_SetBody, 2);
duk_put_prop_string(ctx, j, "SetBody");
return(j);
}
void ILibWebServer_DukTape_OnSession(struct ILibWebServer_Session *SessionToken, void *User)
{
duk_context* ctx = (duk_context*)((void**)SessionToken->ParentExtraMemory)[0];
void* DukOnSession = ((void**)SessionToken->ParentExtraMemory)[1];
duk_push_heapptr(ctx, DukOnSession);
ILibWebServer_DukTape_Push_ILibWebServerSession(ctx, SessionToken);
if (duk_pcall_method(ctx, 0) != 0)
{
ILibDuktape_Process_UncaughtException(ctx);
}
duk_pop(ctx);
}
duk_ret_t ILibWebServer_DukTape_Create(duk_context *ctx)
{
//MaxConnections, PortNumber, OnSession
int MaxConnection = duk_require_int(ctx, 0);
int PortNumber = duk_require_int(ctx, 1);
void* OnSession = duk_require_heapptr(ctx, 2);
void* server;
void* chain;
duk_push_current_function(ctx);
duk_get_prop_string(ctx, -1, "chain");
chain = duk_to_pointer(ctx, -1);
server = ILibWebServer_Create2(chain, MaxConnection, PortNumber, ILibWebServer_DukTape_OnSession, 3 * sizeof(void*), NULL);
((void**)((ILibChain_Link*)server)->ExtraMemoryPtr)[0] = ctx;
((void**)((ILibChain_Link*)server)->ExtraMemoryPtr)[1] = OnSession;
duk_push_heap_stash(ctx);
duk_dup(ctx, 2);
duk_put_prop_string(ctx, -2, Duktape_GetStashKey(server));
return 0;
}
duk_ret_t ILibWebServer_DukTape_CreatePacket(duk_context *ctx)
{
duk_size_t versionLen;
if (!duk_is_string(ctx, 0)) { return(ILibDuktape_Error(ctx, "CreatePacket(): Invalid Parameter/Type")); }
char* version = (char*)duk_get_lstring(ctx, 0, &versionLen);
struct packetheader *header = ILibCreateEmptyPacket();
ILibSetVersion(header, version, (int)versionLen);
ILibWebServer_DukTape_Push_PacketHeader(ctx, header);
return 1;
}
void ILibWebServer_DukTape_Init(duk_context* ctx, void *chain)
{
duk_idx_t i;
duk_push_global_object(ctx); // [global]
i = duk_push_c_function(ctx, ILibWebServer_DukTape_Create, 3); // [global][func]
duk_push_pointer(ctx, chain); // [global][func][ptr]
duk_put_prop_string(ctx, i, "chain"); // [global][func]
duk_put_prop_string(ctx, -2, "ILibWebServer_Create"); // [global]
duk_push_c_function(ctx, ILibWebServer_DukTape_CreatePacket, 1); // [global][func]
duk_put_prop_string(ctx, -2, "ILibWebServer_CreatePacket"); // [global]
Duktape_CreateEnum(ctx, "WebSocket_DataTypes", (char* []){ "UNKNOWN", "REQUEST", "BINARY", "TEXT" }, (int []){ 0x00, 0xFF, 0x2, 0x1 }, 4);
Duktape_CreateEnum(ctx, "WebSocket_FragmentFlags", (char* []) { "INCOMPLETE", "COMPLETE" }, (int[]) { 0, 1 }, 2);
Duktape_CreateEnum(ctx, "WebServer_DoneFlags", (char* []) { "NOTDONE", "DONE", "PARTIAL", "LASTPARTIAL" }, (int[]) { 0, 1, 10, 11 }, 4);
duk_pop(ctx); // ...
}

View File

@@ -0,0 +1,24 @@
/*
Copyright 2006 - 2017 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 ___ILIBWEBSERVERDUKTAPE___
#define ___ILIBWEBSERVERDUKTAPE___
#include "duktape.h"
void ILibWebServer_DukTape_Init(duk_context *ctx, void * chain);
#endif

View File

@@ -0,0 +1,789 @@
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(_MINCORE)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif
#include "duktape.h"
#include "ILibDuktape_EventEmitter.h"
#include "ILibDuktapeModSearch.h"
#include "ILibDuktape_Helpers.h"
#define ILibDuktape_EventEmitter_MaxEventNameLen 255
#define ILibDuktape_EventEmitter_Data "\xFF_EventEmitter_Data"
#define ILibDuktape_EventEmitter_TempObject "\xFF_EventEmitter_TempObject"
#define ILibDuktape_EventEmitter_DispatcherFunc "\xFF_EventEmitter_DispatcherFunc"
#define ILibDuktape_EventEmitter_SetterFunc ((void*)0xFFFF)
#define ILibDuktape_EventEmitter_HPTR_LIST "\xFF_EventEmitter_HPTR_LIST"
#define ILibDuktape_EventEmitter_Hook ((void*)0xEEEE)
#define ILibDuktape_EventEmitter_GlobalListenerCount "\xFF_EventEmitter_GlobalListenerCount"
void ILibDuktape_EventEmitter_ClearListenersSink(void *chain, void *eventList);
#ifdef __DOXY__
/*!
\brief Asynchronous event-driven class, that periodically emit named events that cause Function objects ("listeners") to be called.
*/
class EventEmitter
{
public:
/*!
\brief Adds the listener function to the end of the listeners array for the event specified by eventName.
\param eventName \<String\> The name of the event to associate the listener with.
\param func The listener function to attach.
*/
void on(eventName, func);
/*!
\brief Adds a one time listener function for the event named by eventName. The next time the event is triggered, this listener is removed and then invoked.
\param eventName \<String\> The name of the event to associate the listener with.
\param func The listener function to attach.
*/
void once(eventName, func);
/*!
\brief Synchronously calls each of the listeners registered for the event named by eventName, in the order they were registered, passing the supplied arguments to each.
\param eventName \<String\> The named event whose registered listeners are to be dispatched
\param args <Any> The optional parameters that will be passed to the listener functions.
*/
void emit(eventName[, ...args]);
/*!
\brief Removes the specified listener from the listener array for the event named eventName.
\param eventName \<String\>
\param listener <func>
*/
void removeListener(eventName, listener);
/*!
\brief Removes all listeners, or those of the specified eventName. <b>Note:</b> It is bad practice to remove listeners added elsewhere in the code, particularly when the EventEmitter instance was created by some other component or module.
*
void removeAllListeners([eventName]);
\param eventName \<String\> Optional
*/
void removeAllListeners([eventName]);
/*!
\brief EventEmitter helper class. <b>Note:</b> To use, must <b>require('events')</b>
*/
class events
{
public:
/*!
\brief Adds EventEmitter methods and events to the supplied object
\param obj Normally, <b>'this'</b> object should be passed, so that EventEmitter can be added to it.
\return Returns an events instance object that can be used to add events and methods to the EventEmitter implementation that was integrated
*/
static events inherits(obj);
/*!
\brief Helper method, that will implement the necessary plumbing to expose a named event
*
void createEvent(name);
\param name \<String\> The named event to create
*/
void createEvent(name);
/*!
\brief Helper method, that will implement the necessary plumbing to expose an object instance method. Particularly useful if the method name is the same as a named event.
*
void addMethod(name, func);\n
The instance method will be implemented as a Property, in which the getter returns the supplied function.
\param name The name of the instance method to expose
\param func The function to dispatch when the method is called
*/
void addMethod(name, func);
};
};
#endif
void ILibDuktape_EventEmitter_FinalizerEx(ILibHashtable sender, void *Key1, char* Key2, int Key2Len, void *Data, void *user)
{
ILibDuktape_EventEmitter *data = (ILibDuktape_EventEmitter*)user;
int count, i;
void **hptr;
if (Key1 == NULL)
{
// If this is NULL, then 'Data' is a LinkedList of JavaScript Subscribers
ILibLinkedList_Destroy(Data);
}
else if(Key1 == ILibDuktape_EventEmitter_SetterFunc)
{
// If this is not NULL, this is the JavaScript Setter Func
duk_push_heapptr(data->ctx, Data); // [Setter]
duk_get_prop_string(data->ctx, -1, ILibDuktape_EventEmitter_HPTR_LIST); // [Setter][list]
count = (int)duk_get_length(data->ctx, -1);
for (i = 0; i < count; ++i)
{
duk_get_prop_index(data->ctx, -1, i); // [Setter][list][pointer]
hptr = (void**)duk_get_pointer(data->ctx, -1);
if (hptr != NULL) { *hptr = NULL; }
duk_pop(data->ctx); // [Setter][list]
}
duk_pop_2(data->ctx); // ...
}
}
duk_ret_t ILibDuktape_EventEmitter_Finalizer(duk_context *ctx)
{
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)
{
// 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"))
{
duk_get_prop_string(data->ctx, -1, "\xFF_ExitCode"); // [process][exitCode]
exitCode = duk_get_int(data->ctx, -1);
duk_pop(data->ctx); // [process]
}
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;
}
duk_ret_t ILibDuktape_EventEmitter_emit(duk_context *ctx)
{
duk_size_t nameLen;
if (!duk_is_string(ctx, 0)) { return ILibDuktape_Error(ctx, "EventEmitter.emit(): Invalid Parameter Name/Type"); }
char *name = (char*)duk_get_lstring(ctx, 0, &nameLen);
ILibLinkedList eventList;
void *self;
int nargs = duk_get_top(ctx);
ILibDuktape_EventEmitter *data;
void *node, *nextNode, *func, *dispatcher;
int i, count;
void **hptr;
duk_push_this(ctx);
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);
if (data->eventTable == NULL) { return 0; } // 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); }
node = ILibLinkedList_GetNode_Head(eventList);
while (node != NULL)
{
nextNode = ILibLinkedList_GetNextNode(node);
func = ILibLinkedList_GetDataFromNode(node);
duk_push_heapptr(ctx, func); // [func]
duk_push_heapptr(ctx, self); // [func][this]
for (i = 1; i < nargs; ++i)
{
duk_dup(ctx, i); // [func][this][...args...]
}
if (((int*)ILibLinkedList_GetExtendedMemory(node))[0] == 1)
{
// Dispatch only Once
ILibLinkedList_Remove(node);
data->totalListeners[0]--;
}
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)));
}
duk_pop(ctx); // ...
node = nextNode;
}
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); // ...
}
return 0;
}
int ILibDuktape_EventEmitter_AddOnce(ILibDuktape_EventEmitter *emitter, char *eventName, void *heapptr)
{
int retVal = 1;
duk_push_heapptr(emitter->ctx, emitter->object); // [obj]
duk_get_prop_string(emitter->ctx, -1, "once"); // [obj][once/func]
duk_swap_top(emitter->ctx, -2); // [once/func][this]
duk_push_string(emitter->ctx, eventName); // [once/func][this][eventName]
duk_push_heapptr(emitter->ctx, heapptr); // [once/func][this][eventName][callback]
if (duk_pcall_method(emitter->ctx, 2) == 0) { retVal = 0; }
duk_pop(emitter->ctx); // ...
return retVal;
}
int ILibDuktape_EventEmitter_AddOn(ILibDuktape_EventEmitter *emitter, char *eventName, void *heapptr)
{
int retVal = 1;
duk_push_heapptr(emitter->ctx, emitter->object); // [obj]
duk_get_prop_string(emitter->ctx, -1, "on"); // [obj][once/func]
duk_swap_top(emitter->ctx, -2); // [once/func][this]
duk_push_string(emitter->ctx, eventName); // [once/func][this][eventName]
duk_push_heapptr(emitter->ctx, heapptr); // [once/func][this][eventName][callback]
if (duk_pcall_method(emitter->ctx, 2) == 0) { retVal = 0; }
duk_pop(emitter->ctx); // ...
return retVal;
}
duk_ret_t ILibDuktape_EventEmitter_on(duk_context *ctx)
{
duk_size_t propNameLen;
if (!duk_is_string(ctx, 0)) { return(ILibDuktape_Error(ctx, "EventEmitter.on(): Invalid Parameter Name/Type")); }
char *propName = (char*)duk_get_lstring(ctx, 0, &propNameLen);
void *callback = duk_require_heapptr(ctx, 1);
ILibDuktape_EventEmitter *data;
int once;
void *eventList, *node, *dispatcher, **hptr;
int i, count;
duk_push_current_function(ctx);
once = Duktape_GetIntPropertyValue(ctx, -1, "once", 0);
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_TempObject);
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_Data);
data = (ILibDuktape_EventEmitter*)Duktape_GetBuffer(ctx, -1, NULL);
eventList = ILibHashtable_Get(data->eventTable, NULL, propName, (int)propNameLen);
if (eventList == NULL) { 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)); }
node = ILibLinkedList_AddTail(eventList, callback);
((int*)ILibLinkedList_GetExtendedMemory(node))[0] = once;
data->totalListeners[0]++;
duk_push_heapptr(ctx, data->tmpObject);
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]
}
return 0;
}
ILibDuktape_EventEmitter* ILibDuktape_EventEmitter_GetEmitter_fromThis(duk_context *ctx)
{
ILibDuktape_EventEmitter *retVal = NULL;
duk_push_this(ctx); // [this]
retVal = ILibDuktape_EventEmitter_GetEmitter_fromCurrent(ctx);
duk_pop(ctx); // ...
return retVal;
}
ILibDuktape_EventEmitter* ILibDuktape_EventEmitter_GetEmitter(duk_context *ctx, duk_idx_t i)
{
ILibDuktape_EventEmitter *retVal = NULL;
if (duk_has_prop_string(ctx, i, ILibDuktape_EventEmitter_TempObject))
{
// This object already has an EventEmitter
duk_get_prop_string(ctx, i, ILibDuktape_EventEmitter_TempObject); // [tmp]
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_Data); // [tmp][data]
retVal = (ILibDuktape_EventEmitter*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop_2(ctx);
}
return retVal;
}
duk_ret_t ILibDuktape_EventEmitter_removeListener(duk_context *ctx)
{
void *callback = duk_require_heapptr(ctx, 1);
duk_size_t eventNameLen;
char *eventName = Duktape_GetBuffer(ctx, 0, &eventNameLen);
ILibDuktape_EventEmitter *emitter = ILibDuktape_EventEmitter_GetEmitter_fromThis(ctx);
void *eventList;
void *node;
if (emitter != NULL)
{
eventList = ILibHashtable_Get(emitter->eventTable, NULL, eventName, (int)eventNameLen);
if (eventList == NULL) { return(ILibDuktape_Error(ctx, "EventEmitter.removeListener(): Event '%s' not found", eventName)); }
node = ILibLinkedList_GetNode_Search(eventList, NULL, callback);
if (node != NULL)
{
ILibLinkedList_Remove(node);
emitter->totalListeners[0]--;
}
}
return(0);
}
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;
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]
}
//Use this callback, just in case we were called from an event dispatch. Don't want to clear it during a dispatch, cause we'll crash
ILibChain_RunOnMicrostackThreadEx(Duktape_GetChain(ctx), ILibDuktape_EventEmitter_ClearListenersSink, eventList);
emitter->totalListeners[0] = 0;
}
return(0);
}
ILibDuktape_EventEmitter* ILibDuktape_EventEmitter_Create(duk_context *ctx)
{
ILibDuktape_EventEmitter *retVal;
if (duk_has_prop_string(ctx, -1, ILibDuktape_EventEmitter_TempObject))
{
// This object already has an EventEmitter
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_TempObject); // [tmp]
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_Data); // [tmp][data]
retVal = (ILibDuktape_EventEmitter*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop_2(ctx);
return retVal;
}
duk_push_object(ctx); // [emitterTmp]
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_EventEmitter)); // [emitterTmp][data]
retVal = (ILibDuktape_EventEmitter*)Duktape_GetBuffer(ctx, -1, NULL);
memset(retVal, 0, sizeof(ILibDuktape_EventEmitter));
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();
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "once", 1, "once", ILibDuktape_EventEmitter_on, 2);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "once", 0, "on", ILibDuktape_EventEmitter_on, 2);
ILibDuktape_CreateInstanceMethod(ctx, "removeListener", ILibDuktape_EventEmitter_removeListener, 2);
ILibDuktape_CreateInstanceMethod(ctx, "removeAllListeners", ILibDuktape_EventEmitter_removeAllListeners, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "emit", ILibDuktape_EventEmitter_emit, DUK_VARARGS);
duk_push_heap_stash(ctx);
if (duk_has_prop_string(ctx, -1, ILibDuktape_EventEmitter_GlobalListenerCount))
{
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_GlobalListenerCount);
retVal->totalListeners = (unsigned int *)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop(ctx);
}
else
{
duk_push_fixed_buffer(ctx, sizeof(unsigned int));
retVal->totalListeners = (unsigned int *)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, ILibDuktape_EventEmitter_GlobalListenerCount);
*(retVal->totalListeners) = 0;
}
duk_pop(ctx);
return retVal;
}
void ILibDuktape_EventEmitter_ClearListenersSink(void *chain, void *eventList)
{
ILibLinkedList_Clear(eventList);
}
void ILibDuktape_EventEmitter_AddHook(ILibDuktape_EventEmitter *emitter, char *eventName, ILibDuktape_EventEmitter_HookHandler handler)
{
if (ILibHashtable_Get(emitter->eventTable, ILibDuktape_EventEmitter_Hook, eventName, strnlen_s(eventName, 255)) == NULL && handler != NULL)
{
ILibHashtable_Put(emitter->eventTable, ILibDuktape_EventEmitter_Hook, eventName, strnlen_s(eventName, 255), handler);
}
}
duk_ret_t ILibDuktape_EventEmitter_SetEvent(duk_context *ctx)
{
char *propName;
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]
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]
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_Data); // [this][tmp][data]
data = (ILibDuktape_EventEmitter*)Duktape_GetBuffer(ctx, -1, NULL);
eventList = ILibHashtable_Get(data->eventTable, NULL, propName, (int)propNameLen);
if (eventList == NULL) { return(ILibDuktape_Error(ctx, "EventEmitter(): Cannot add listener becuase event '%s' is not found", propName)); }
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]
}
//Use this callback, just in case we were called from an event dispatch. Don't want to clear it during a dispatch
ILibChain_RunOnMicrostackThread(Duktape_GetChain(ctx), ILibDuktape_EventEmitter_ClearListenersSink, eventList);
}
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);
}
}
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]
duk_get_prop_string(emitter->ctx, -1, "removeAllListeners"); // [this][func]
duk_swap_top(emitter->ctx, -2); // [func][this]
duk_push_string(emitter->ctx, eventName); // [func][this][eventName]
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)
{
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)
{
// 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 = 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); // ...
}
}
int ILibDuktape_EventEmitter_AddEventHeapptr(ILibDuktape_EventEmitter *emitter, char *eventName, void **heapptr)
{
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); // ...
// 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)
{
// 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); // ...
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_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));
}
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);
return 0;
}
duk_ret_t ILibDuktape_EventEmitter_Inherits_addMethod(duk_context *ctx)
{
ILibDuktape_EventEmitter *emitter;
duk_push_this(ctx); // [emitterUtils]
duk_get_prop_string(ctx, -1, "emitter"); // [emitterUtils][ptr]
emitter = (ILibDuktape_EventEmitter*)duk_get_pointer(ctx, -1);
duk_push_heapptr(ctx, emitter->object); // [emitterUtils][ptr][target]
ILibDuktape_CreateProperty_InstanceMethodEx(ctx, (char*)duk_require_string(ctx, 0), duk_require_heapptr(ctx, 1));
return(0);
}
duk_ret_t ILibDuktape_EventEmitter_Inherits(duk_context *ctx)
{
ILibDuktape_EventEmitter *emitter;
duk_dup(ctx, 0); // [target]
emitter = ILibDuktape_EventEmitter_Create(ctx);
duk_push_object(ctx); // [target][emitterUtils]
duk_dup(ctx, -1); // [target][emitterUtils][dup]
duk_put_prop_string(ctx, -3, "\xFF_emitterUtils"); // [target][emitterUtils]
duk_push_pointer(ctx, emitter); // [target][emitterUtils][ptr]
duk_put_prop_string(ctx, -2, "emitter"); // [target][emitterUtils]
ILibDuktape_CreateInstanceMethod(ctx, "createEvent", ILibDuktape_EventEmitter_Inherits_createEvent, 1);
ILibDuktape_CreateInstanceMethod(ctx, "addMethod", ILibDuktape_EventEmitter_Inherits_addMethod, 2);
return 1;
}
void ILibDuktape_EventEmitter_PUSH(duk_context *ctx, void *chain)
{
duk_push_object(ctx); // [emitter]
ILibDuktape_CreateInstanceMethod(ctx, "inherits", ILibDuktape_EventEmitter_Inherits, 1);
}
void ILibDuktape_EventEmitter_Init(duk_context *ctx)
{
ILibDuktape_ModSearch_AddHandler(ctx, "events", ILibDuktape_EventEmitter_PUSH);
}

2457
microscript/Microscript.doxy Normal file

File diff suppressed because it is too large Load Diff

3804
microscript/duk_config.h Normal file

File diff suppressed because it is too large Load Diff

86982
microscript/duktape.c Normal file

File diff suppressed because it is too large Load Diff

1581
microscript/duktape.h Normal file

File diff suppressed because it is too large Load Diff