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:
265
microscript/ILibAsyncSocket_Duktape.c
Normal file
265
microscript/ILibAsyncSocket_Duktape.c
Normal 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); //
|
||||
}
|
||||
25
microscript/ILibAsyncSocket_Duktape.h
Normal file
25
microscript/ILibAsyncSocket_Duktape.h
Normal 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
|
||||
227
microscript/ILibDuktapeModSearch.c
Normal file
227
microscript/ILibDuktapeModSearch.c
Normal 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);
|
||||
}
|
||||
29
microscript/ILibDuktapeModSearch.h
Normal file
29
microscript/ILibDuktapeModSearch.h
Normal 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
|
||||
90
microscript/ILibDuktape_Debugger.c
Normal file
90
microscript/ILibDuktape_Debugger.c
Normal 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)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
26
microscript/ILibDuktape_Debugger.h
Normal file
26
microscript/ILibDuktape_Debugger.h
Normal 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
|
||||
562
microscript/ILibDuktape_Dgram.c
Normal file
562
microscript/ILibDuktape_Dgram.c
Normal 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
|
||||
9
microscript/ILibDuktape_Dgram.h
Normal file
9
microscript/ILibDuktape_Dgram.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef ___ILibDuktape_Dgram___
|
||||
#define ___ILibDuktape_Dgram___
|
||||
|
||||
#include "duktape.h"
|
||||
|
||||
void ILibDuktape_DGram_Init(duk_context *ctx);
|
||||
|
||||
|
||||
#endif
|
||||
74
microscript/ILibDuktape_DuplexStream.c
Normal file
74
microscript/ILibDuktape_DuplexStream.c
Normal 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;
|
||||
}
|
||||
51
microscript/ILibDuktape_DuplexStream.h
Normal file
51
microscript/ILibDuktape_DuplexStream.h
Normal 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
|
||||
253
microscript/ILibDuktape_EncryptionStream.c
Normal file
253
microscript/ILibDuktape_EncryptionStream.c
Normal 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
|
||||
8
microscript/ILibDuktape_EncryptionStream.h
Normal file
8
microscript/ILibDuktape_EncryptionStream.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef __ILibDuktape_EncryptionStream__
|
||||
#define __ILibDuktape_EncryptionStream__
|
||||
|
||||
#include "duktape.h"
|
||||
|
||||
void ILibDuktape_EncryptionStream_init(duk_context *ctx);
|
||||
|
||||
#endif
|
||||
37
microscript/ILibDuktape_EventEmitter.h
Normal file
37
microscript/ILibDuktape_EventEmitter.h
Normal 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
|
||||
873
microscript/ILibDuktape_GenericMarshal.c
Normal file
873
microscript/ILibDuktape_GenericMarshal.c
Normal 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
|
||||
26
microscript/ILibDuktape_GenericMarshal.h
Normal file
26
microscript/ILibDuktape_GenericMarshal.h
Normal 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
|
||||
595
microscript/ILibDuktape_Helpers.c
Normal file
595
microscript/ILibDuktape_Helpers.c
Normal 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);
|
||||
}
|
||||
86
microscript/ILibDuktape_Helpers.h
Normal file
86
microscript/ILibDuktape_Helpers.h
Normal 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
|
||||
123
microscript/ILibDuktape_MemoryStream.c
Normal file
123
microscript/ILibDuktape_MemoryStream.c
Normal 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);
|
||||
}
|
||||
146
microscript/ILibDuktape_NetworkMonitor.c
Normal file
146
microscript/ILibDuktape_NetworkMonitor.c
Normal 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);
|
||||
}
|
||||
32
microscript/ILibDuktape_NetworkMonitor.h
Normal file
32
microscript/ILibDuktape_NetworkMonitor.h
Normal 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
|
||||
604
microscript/ILibDuktape_Polyfills.c
Normal file
604
microscript/ILibDuktape_Polyfills.c
Normal 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
|
||||
8
microscript/ILibDuktape_Polyfills.h
Normal file
8
microscript/ILibDuktape_Polyfills.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef __ILibDuktape_Polyfills__
|
||||
#define __ILibDuktape_Polyfills__
|
||||
|
||||
#include "duktape.h"
|
||||
|
||||
void ILibDuktape_Polyfills_Init(duk_context *ctx);
|
||||
|
||||
#endif
|
||||
256
microscript/ILibDuktape_ProcessPipe.c
Normal file
256
microscript/ILibDuktape_ProcessPipe.c
Normal 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);
|
||||
}
|
||||
71
microscript/ILibDuktape_ProcessPipe.h
Normal file
71
microscript/ILibDuktape_ProcessPipe.h
Normal 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
|
||||
718
microscript/ILibDuktape_ReadableStream.c
Normal file
718
microscript/ILibDuktape_ReadableStream.c
Normal 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;
|
||||
}
|
||||
73
microscript/ILibDuktape_ReadableStream.h
Normal file
73
microscript/ILibDuktape_ReadableStream.h
Normal 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
|
||||
|
||||
477
microscript/ILibDuktape_SHA256.c
Normal file
477
microscript/ILibDuktape_SHA256.c
Normal 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
|
||||
10
microscript/ILibDuktape_SHA256.h
Normal file
10
microscript/ILibDuktape_SHA256.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef ___DUKTAPE_SHA256___
|
||||
#define ___DUKTAPE_SHA256___
|
||||
|
||||
|
||||
#include "duktape.h"
|
||||
|
||||
void ILibDuktape_SHA256_Init(duk_context *ctx);
|
||||
|
||||
|
||||
#endif
|
||||
1611
microscript/ILibDuktape_ScriptContainer.c
Normal file
1611
microscript/ILibDuktape_ScriptContainer.c
Normal file
File diff suppressed because it is too large
Load Diff
158
microscript/ILibDuktape_ScriptContainer.h
Normal file
158
microscript/ILibDuktape_ScriptContainer.h
Normal 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
|
||||
|
||||
286
microscript/ILibDuktape_SimpleDataStore.c
Normal file
286
microscript/ILibDuktape_SimpleDataStore.c
Normal 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
|
||||
27
microscript/ILibDuktape_SimpleDataStore.h
Normal file
27
microscript/ILibDuktape_SimpleDataStore.h
Normal 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
|
||||
538
microscript/ILibDuktape_WebRTC.c
Normal file
538
microscript/ILibDuktape_WebRTC.c
Normal 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
|
||||
8
microscript/ILibDuktape_WebRTC.h
Normal file
8
microscript/ILibDuktape_WebRTC.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef ___ILibDuktape_WebRTC___
|
||||
#define ___ILibDuktape_WebRTC___
|
||||
|
||||
#include "duktape.h"
|
||||
|
||||
void ILibDuktape_WebRTC_Init(duk_context *ctx);
|
||||
|
||||
#endif
|
||||
293
microscript/ILibDuktape_WritableStream.c
Normal file
293
microscript/ILibDuktape_WritableStream.c
Normal 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;
|
||||
}
|
||||
55
microscript/ILibDuktape_WritableStream.h
Normal file
55
microscript/ILibDuktape_WritableStream.h
Normal 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
1443
microscript/ILibDuktape_fs.c
Normal file
File diff suppressed because it is too large
Load Diff
9
microscript/ILibDuktape_fs.h
Normal file
9
microscript/ILibDuktape_fs.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef ___DUKTAPE_FS___
|
||||
#define ___DUKTAPE_FS___
|
||||
|
||||
#include "duktape.h"
|
||||
|
||||
void ILibDuktape_fs_init(duk_context *ctx);
|
||||
|
||||
|
||||
#endif
|
||||
2976
microscript/ILibDuktape_http.c
Normal file
2976
microscript/ILibDuktape_http.c
Normal file
File diff suppressed because it is too large
Load Diff
25
microscript/ILibDuktape_http.h
Normal file
25
microscript/ILibDuktape_http.h
Normal 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
|
||||
|
||||
1160
microscript/ILibDuktape_net.c
Normal file
1160
microscript/ILibDuktape_net.c
Normal file
File diff suppressed because it is too large
Load Diff
42
microscript/ILibDuktape_net.h
Normal file
42
microscript/ILibDuktape_net.h
Normal 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
|
||||
124
microscript/ILibParsers_Duktape.c
Normal file
124
microscript/ILibParsers_Duktape.c
Normal 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
|
||||
}
|
||||
24
microscript/ILibParsers_Duktape.h
Normal file
24
microscript/ILibParsers_Duktape.h
Normal 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
|
||||
576
microscript/ILibWebClient_Duktape.c
Normal file
576
microscript/ILibWebClient_Duktape.c
Normal 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);
|
||||
}
|
||||
25
microscript/ILibWebClient_Duktape.h
Normal file
25
microscript/ILibWebClient_Duktape.h
Normal 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
|
||||
717
microscript/ILibWebServer_Duktape.c
Normal file
717
microscript/ILibWebServer_Duktape.c
Normal 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); // ...
|
||||
}
|
||||
24
microscript/ILibWebServer_Duktape.h
Normal file
24
microscript/ILibWebServer_Duktape.h
Normal 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
|
||||
789
microscript/ILibduktape_EventEmitter.c
Normal file
789
microscript/ILibduktape_EventEmitter.c
Normal 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
2457
microscript/Microscript.doxy
Normal file
File diff suppressed because it is too large
Load Diff
3804
microscript/duk_config.h
Normal file
3804
microscript/duk_config.h
Normal file
File diff suppressed because it is too large
Load Diff
86982
microscript/duktape.c
Normal file
86982
microscript/duktape.c
Normal file
File diff suppressed because it is too large
Load Diff
1581
microscript/duktape.h
Normal file
1581
microscript/duktape.h
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user