1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2025-12-06 00:13:33 +00:00
Files
MeshAgent/microscript/ILibAsyncSocket_Duktape.c
2017-10-12 14:28:03 -07:00

266 lines
11 KiB
C

/*
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); //
}