mirror of
https://github.com/Ylianst/MeshAgent
synced 2025-12-24 04:04:31 +00:00
1. Added ILibChain_WriteEx()
2. Updated ILibChain_Continue() on windows to take an optional list of HANDLE** 3. Updated net.socket IPC on Windows to use ILibChain_ReadEx and ILibChain_WriteEx 4. Fixed child_process.waitExit() on windows to pass only the wait handles for the process 5. Added GetWaitHandles() to ILibProcessPipe
This commit is contained in:
@@ -170,6 +170,7 @@ duk_ret_t ILibDuktape_ChildProcess_waitExit(duk_context *ctx)
|
||||
}
|
||||
|
||||
duk_push_this(ctx); // [spawnedProcess]
|
||||
char *_target = Duktape_GetStringPropertyValue(ctx, -1, "_target", NULL);
|
||||
if (!ILibChain_IsLinkAlive(Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Manager)))
|
||||
{
|
||||
return(ILibDuktape_Error(ctx, "Cannot waitExit() because JS Engine is exiting"));
|
||||
@@ -179,7 +180,14 @@ duk_ret_t ILibDuktape_ChildProcess_waitExit(duk_context *ctx)
|
||||
duk_put_prop_string(ctx, -2, "\xFF_WaitExit"); // [spawnedProcess]
|
||||
|
||||
void *mods[] = { ILibGetBaseTimer(Duktape_GetChain(ctx)), Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Manager) };
|
||||
#ifdef WIN32
|
||||
HANDLE handles[] = { NULL, NULL, NULL, NULL };
|
||||
ILibProcessPipe_Process p = Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Process);
|
||||
ILibProcessPipe_Process_GetWaitHandles(p, &(handles[0]), &(handles[1]), &(handles[2]), &(handles[3]));
|
||||
ILibChain_Continue(chain, (ILibChain_Link**)mods, 2, timeout, (HANDLE**)handles);
|
||||
#else
|
||||
ILibChain_Continue(chain, (ILibChain_Link**)mods, 2, timeout);
|
||||
#endif
|
||||
|
||||
return(0);
|
||||
}
|
||||
@@ -396,6 +404,7 @@ duk_ret_t ILibDuktape_ChildProcess_execFile(duk_context *ctx)
|
||||
return(ILibDuktape_Error(ctx, "child_process.execFile(): Could not exec [%s]", target));
|
||||
}
|
||||
ILibDuktape_ChildProcess_SpawnedProcess_PUSH(ctx, p, callback);
|
||||
duk_push_string(ctx, target); duk_put_prop_string(ctx, -2, "_target");
|
||||
duk_push_pointer(ctx, manager); duk_put_prop_string(ctx, -2, ILibDuktape_ChildProcess_Manager);
|
||||
return(1);
|
||||
}
|
||||
|
||||
@@ -93,6 +93,9 @@ void *Duktape_Duplicate_GetBufferPropertyEx(duk_context *ctx, duk_idx_t i, char*
|
||||
char *Duktape_Duplicate_GetStringEx(duk_context *ctx, duk_idx_t i, duk_size_t *len);
|
||||
#define Duktape_Duplicate_GetString(ctx, i) Duktape_Duplicate_GetStringEx(ctx, i, NULL)
|
||||
|
||||
#define duk_array_shift(ctx, i) duk_dup(ctx, i);duk_get_prop_string(ctx, -1, "shift");duk_swap_top(ctx, -2);duk_call_method(ctx, 0);
|
||||
#define duk_array_pop(ctx, i) duk_dup(ctx, i);duk_get_prop_string(ctx, -1, "pop");duk_swap_top(ctx, -2);duk_call_method(ctx, 0);
|
||||
|
||||
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);
|
||||
|
||||
@@ -82,14 +82,18 @@ int ILibDuktape_TLS_ctx2server = -1;
|
||||
#define ILibDuktape_net_IPC_BUFFERSIZE 4096
|
||||
typedef struct ILibDuktape_net_WindowsIPC
|
||||
{
|
||||
ILibProcessPipe_Manager manager;
|
||||
duk_context *ctx;
|
||||
void *mServer, *mSocket, *mChain;
|
||||
HANDLE mPipeHandle;
|
||||
ILibProcessPipe_Pipe mPipe;
|
||||
int paused;
|
||||
int totalRead;
|
||||
void *user1;
|
||||
|
||||
OVERLAPPED read_overlapped;
|
||||
OVERLAPPED write_overlapped;
|
||||
OVERLAPPED overlapped;
|
||||
ILibDuktape_DuplexStream *ds;
|
||||
BOOL clientConnected;
|
||||
|
||||
ULONG_PTR _reserved[5];
|
||||
|
||||
@@ -377,13 +381,12 @@ duk_ret_t ILibDuktape_net_socket_connect(duk_context *ctx)
|
||||
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)Duktape_PushBuffer(ctx, sizeof(ILibDuktape_net_WindowsIPC));
|
||||
duk_put_prop_string(ctx, -2, ILibDuktape_net_WindowsIPC_Buffer);
|
||||
winIPC->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
winIPC->read_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
winIPC->write_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
winIPC->ctx = ctx;
|
||||
winIPC->mSocket = duk_get_heapptr(ctx, -1);
|
||||
winIPC->mChain = Duktape_GetChain(ctx);
|
||||
|
||||
duk_eval_string(ctx, "require('child_process');");
|
||||
winIPC->manager = (ILibProcessPipe_Manager)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Manager);
|
||||
duk_pop(ctx);
|
||||
winIPC->mChain = duk_ctx_chain(ctx);
|
||||
winIPC->paused = 1;
|
||||
|
||||
if ((winIPC->mPipeHandle = CreateFileA(path, GENERIC_READ | FILE_WRITE_DATA, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0)) == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
@@ -394,7 +397,6 @@ duk_ret_t ILibDuktape_net_socket_connect(duk_context *ctx)
|
||||
{
|
||||
// SUCCESS
|
||||
winIPC->ds = ILibDuktape_DuplexStream_InitEx(winIPC->ctx, ILibDuktape_net_server_IPC_WriteSink, ILibDuktape_net_server_IPC_EndSink, ILibDuktape_net_server_IPC_PauseSink, ILibDuktape_net_server_IPC_ResumeSink, ILibDuktape_net_server_IPC_unshiftSink, winIPC);
|
||||
winIPC->mPipe = ILibProcessPipe_Pipe_CreateFromExisting(winIPC->manager, winIPC->mPipeHandle, ILibProcessPipe_Pipe_ReaderHandleType_Overlapped);
|
||||
winIPC->ds->readableStream->paused = 1;
|
||||
ILibDuktape_EventEmitter_AddHook(ILibDuktape_EventEmitter_GetEmitter(winIPC->ctx, -1), "data", ILibDuktape_net_socket_ipc_dataHookCallback);
|
||||
ILibDuktape_EventEmitter_AddHook(ILibDuktape_EventEmitter_GetEmitter(winIPC->ctx, -1), "end", ILibDuktape_net_socket_ipc_dataHookCallback);
|
||||
@@ -837,7 +839,99 @@ void ILibDuktape_net_server_OnSendOK(ILibAsyncServerSocket_ServerModule AsyncSer
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
extern void ILibProcessPipe_FreePipe(ILibProcessPipe_Pipe pipeObject);
|
||||
BOOL ILibDuktape_server_ipc_ReadSink(void *chain, HANDLE h, ILibWaitHandle_ErrorStatus status, char *buffer, int bytesRead, void* user)
|
||||
{
|
||||
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user;
|
||||
int consumed = 0;
|
||||
|
||||
if (status == ILibWaitHandle_ErrorStatus_NONE)
|
||||
{
|
||||
winIPC->totalRead += bytesRead;
|
||||
do
|
||||
{
|
||||
winIPC->unshiftedBytes = 0;
|
||||
if (winIPC->totalRead > 0)
|
||||
{
|
||||
ILibDuktape_DuplexStream_WriteData(winIPC->ds, winIPC->buffer + winIPC->bufferOffset, winIPC->totalRead);
|
||||
}
|
||||
if (winIPC->unshiftedBytes > winIPC->totalRead) { winIPC->unshiftedBytes = winIPC->totalRead; }
|
||||
winIPC->bufferOffset += (winIPC->totalRead - winIPC->unshiftedBytes);
|
||||
winIPC->totalRead -= (winIPC->totalRead - winIPC->unshiftedBytes);
|
||||
} while (winIPC->paused == 0 && consumed != 0 && winIPC->totalRead > 0);
|
||||
if (winIPC->totalRead == 0) { winIPC->bufferOffset = 0; }
|
||||
if (winIPC->paused == 0)
|
||||
{
|
||||
if (winIPC->bufferOffset > 0)
|
||||
{
|
||||
memmove_s(winIPC->buffer, winIPC->bufferLength, winIPC->buffer + winIPC->bufferOffset, winIPC->totalRead);
|
||||
winIPC->bufferOffset = 0;
|
||||
}
|
||||
else if (winIPC->totalRead == winIPC->bufferLength)
|
||||
{
|
||||
ILibMemory_ReallocateRaw(&(winIPC->buffer), winIPC->bufferLength == 0 ? ILibDuktape_net_IPC_BUFFERSIZE : winIPC->bufferLength * 2);
|
||||
winIPC->bufferLength = winIPC->bufferLength == 0 ? ILibDuktape_net_IPC_BUFFERSIZE : winIPC->bufferLength * 2;
|
||||
}
|
||||
ILibChain_ReadEx(chain, h, &(winIPC->read_overlapped), winIPC->buffer + winIPC->bufferOffset + winIPC->totalRead, winIPC->bufferLength - winIPC->totalRead, ILibDuktape_server_ipc_ReadSink, winIPC);
|
||||
return(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// I/O Errors
|
||||
ILibDuktape_DuplexStream_Closed(winIPC->ds);
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
BOOL ILibDuktape_server_ipc_WriteSink(void *chain, HANDLE h, ILibWaitHandle_ErrorStatus status, int bytesWritten, void* user)
|
||||
{
|
||||
if (!ILibMemory_CanaryOK(user)) { return(FALSE); }
|
||||
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user;
|
||||
duk_idx_t top = duk_get_top(winIPC->ctx);
|
||||
duk_size_t bufLen;
|
||||
char *buf;
|
||||
ILibTransport_DoneState d = ILibTransport_DoneState_COMPLETE;
|
||||
BOOL ret;
|
||||
|
||||
duk_push_heapptr(winIPC->ctx, winIPC->mSocket); // [obj]
|
||||
duk_get_prop_string(winIPC->ctx, -1, ILibDuktape_net_WindowsIPC_PendingArray); // [obj][array]
|
||||
|
||||
while (d == ILibTransport_DoneState_COMPLETE)
|
||||
{
|
||||
duk_dup(winIPC->ctx, -1); // [obj][array][array]
|
||||
duk_get_prop_string(winIPC->ctx, -1, "shift"); // [obj][array][array][shift]
|
||||
duk_swap_top(winIPC->ctx, -2); // [obj][array][shift][this]
|
||||
if (duk_pcall_method(winIPC->ctx, 0) != 0) { duk_set_top(winIPC->ctx, top); return(FALSE); } // [obj][array][buffer]
|
||||
duk_pop(winIPC->ctx); // [obj][array]
|
||||
if (duk_get_length(winIPC->ctx, -1) == 0) { break; }
|
||||
duk_get_prop_index(winIPC->ctx, -1, 0); // [obj][array][buffer]
|
||||
buf = Duktape_GetBuffer(winIPC->ctx, -1, &bufLen);
|
||||
d = ILibChain_WriteEx(chain, h, &(winIPC->write_overlapped), buf, (int)bufLen, ILibDuktape_server_ipc_WriteSink, winIPC);
|
||||
duk_pop(winIPC->ctx); // [obj][array]
|
||||
}
|
||||
|
||||
switch (d)
|
||||
{
|
||||
case ILibTransport_DoneState_COMPLETE:
|
||||
// No more pending writes, so we can emit drain
|
||||
ILibDuktape_DuplexStream_Ready(winIPC->ds);
|
||||
ret = FALSE;
|
||||
break;
|
||||
case ILibTransport_DoneState_INCOMPLETE:
|
||||
// Still pending writes, so return TRUE, so we can get evented later
|
||||
ret = TRUE;
|
||||
break;
|
||||
case ILibTransport_DoneState_ERROR:
|
||||
ret = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
duk_set_top(winIPC->ctx, top); // ...
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int ILibDuktape_net_server_IPC_unshiftSink(ILibDuktape_DuplexStream *sender, int unshiftBytes, void *user)
|
||||
{
|
||||
@@ -846,166 +940,29 @@ int ILibDuktape_net_server_IPC_unshiftSink(ILibDuktape_DuplexStream *sender, int
|
||||
winIPC->unshiftedBytes = unshiftBytes;
|
||||
return(unshiftBytes);
|
||||
}
|
||||
void ILibDuktape_net_server_IPC_readsink(ILibProcessPipe_Pipe sender, void *user, DWORD dwErrorCode, char *buffer, int bufferLen)
|
||||
{
|
||||
if (!ILibMemory_CanaryOK(user)) { return; }
|
||||
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user;
|
||||
|
||||
if (dwErrorCode == 0)
|
||||
{
|
||||
winIPC->bytesLeft += bufferLen;
|
||||
ILibDuktape_net_server_IPC_ResumeSink(winIPC->ds, winIPC);
|
||||
}
|
||||
else
|
||||
{
|
||||
ILibDuktape_DuplexStream_Closed(winIPC->ds);
|
||||
ILibProcessPipe_FreePipe(winIPC->mPipe);
|
||||
winIPC->mPipe = NULL; winIPC->mPipeHandle = NULL;
|
||||
if (winIPC->buffer != NULL) { free(winIPC->buffer); winIPC->buffer = NULL; }
|
||||
if (winIPC->mServer != NULL)
|
||||
{
|
||||
// Server IPC, so we can create a new Instance, and listen for a connection
|
||||
duk_context *ctx = winIPC->ctx; // We need to dereference this, because winIPC will go out of scope when we call listen
|
||||
CloseHandle(winIPC->overlapped.hEvent); winIPC->overlapped.hEvent = NULL;
|
||||
|
||||
duk_push_heapptr(winIPC->ctx, winIPC->mSocket); // [connection]
|
||||
duk_del_prop_string(ctx, -1, ILibDuktape_net_WindowsIPC_Buffer); duk_pop(winIPC->ctx); // ...
|
||||
|
||||
duk_push_heapptr(ctx, winIPC->mServer); // [server]
|
||||
if (Duktape_GetBooleanProperty(ctx, -1, ILibDuktape_net_server_closed, 0) == 0)
|
||||
{
|
||||
duk_get_prop_string(ctx, -1, "listen"); // [server][listen]
|
||||
duk_swap_top(ctx, -2); // [listen][this]
|
||||
duk_get_prop_string(ctx, -1, ILibDuktape_SERVER2LISTENOPTIONS); // [listen][this][options]
|
||||
duk_pcall_method(ctx, 1); // [ret]
|
||||
}
|
||||
else if (Duktape_GetBooleanProperty(ctx, -1, ILibDuktape_net_server_closed_needEmit, 0) != 0)
|
||||
{
|
||||
duk_push_false(ctx); duk_put_prop_string(ctx, -2, ILibDuktape_net_server_closed_needEmit);
|
||||
ILibDuktape_EventEmitter_SetupEmit(ctx, winIPC->mServer, "close"); // [emit][this][closed]
|
||||
duk_pcall_method(ctx, 1); // [ret]
|
||||
}
|
||||
duk_pop(ctx); // ...
|
||||
}
|
||||
}
|
||||
}
|
||||
void ILibDuktape_net_server_IPC_PauseSink(ILibDuktape_DuplexStream *sender, void *user)
|
||||
{
|
||||
// No-OP, becuase all we need to so is set Paused flag, which is already the case when we get here
|
||||
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user;
|
||||
winIPC->paused = 1;
|
||||
}
|
||||
void ILibDuktape_net_server_IPC_ResumeSink(ILibDuktape_DuplexStream *sender, void *user)
|
||||
{
|
||||
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user;
|
||||
if (winIPC->mPipeHandle == NULL) { return; }
|
||||
|
||||
if (winIPC->buffer == NULL)
|
||||
{
|
||||
winIPC->buffer = ILibMemory_Allocate(ILibDuktape_net_IPC_BUFFERSIZE, 0, NULL, NULL);
|
||||
winIPC->bufferLength = ILibDuktape_net_IPC_BUFFERSIZE;
|
||||
winIPC->bufferOffset = 0;
|
||||
winIPC->bytesLeft = 0;
|
||||
winIPC->paused = 0;
|
||||
ILibDuktape_server_ipc_ReadSink(winIPC->mChain, winIPC->mPipeHandle, ILibWaitHandle_ErrorStatus_NONE, NULL, 0, winIPC);
|
||||
}
|
||||
|
||||
if (winIPC->bytesLeft <= 0)
|
||||
{
|
||||
winIPC->bytesLeft = 0;
|
||||
winIPC->bufferOffset = 0;
|
||||
if (ILibProcessPipe_Pipe_ReadEx(winIPC->mPipe, winIPC->buffer, winIPC->bufferLength, winIPC, ILibDuktape_net_server_IPC_readsink) != 0)
|
||||
{
|
||||
ILibDuktape_net_server_IPC_readsink(winIPC->mPipe, winIPC, 1, NULL, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check to see if we can drain any of the buffer first
|
||||
while (winIPC->ds->readableStream->paused == 0)
|
||||
{
|
||||
winIPC->unshiftedBytes = 0;
|
||||
ILibDuktape_DuplexStream_WriteData(winIPC->ds, winIPC->buffer + winIPC->bufferOffset, winIPC->bytesLeft);
|
||||
if (winIPC->mPipe == NULL) { return; } // We return here without resetting processingRead, because IO was canceled
|
||||
if (winIPC->unshiftedBytes > 0)
|
||||
{
|
||||
if (winIPC->unshiftedBytes == winIPC->bytesLeft)
|
||||
{
|
||||
// Unshift the entire buffer
|
||||
winIPC->unshiftedBytes = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unshift some of the buffer
|
||||
winIPC->bufferOffset += (winIPC->bytesLeft - winIPC->unshiftedBytes);
|
||||
if (winIPC->bytesLeft == winIPC->unshiftedBytes)
|
||||
{
|
||||
winIPC->unshiftedBytes = 0;
|
||||
}
|
||||
winIPC->bytesLeft = winIPC->unshiftedBytes;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
winIPC->bufferOffset = winIPC->bytesLeft = 0;
|
||||
}
|
||||
|
||||
if (winIPC->ds->readableStream->paused == 0 && (winIPC->bytesLeft == 0 || (winIPC->bytesLeft > 0 && winIPC->unshiftedBytes == 0)))
|
||||
{
|
||||
if (winIPC->bufferLength - winIPC->bufferOffset - winIPC->bytesLeft == 0)
|
||||
{
|
||||
// We need to grow the buffer
|
||||
ILibMemory_ReallocateRaw(&(winIPC->buffer), winIPC->bufferLength + ILibDuktape_net_IPC_BUFFERSIZE);
|
||||
winIPC->bufferLength += ILibDuktape_net_IPC_BUFFERSIZE;
|
||||
}
|
||||
if (ILibProcessPipe_Pipe_ReadEx(winIPC->mPipe, winIPC->buffer + winIPC->bufferOffset + winIPC->bytesLeft, winIPC->bufferLength - winIPC->bufferOffset - winIPC->bytesLeft, winIPC, ILibDuktape_net_server_IPC_readsink) != 0)
|
||||
{
|
||||
ILibDuktape_net_server_IPC_readsink(winIPC->mPipe, winIPC, 1, NULL, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void ILibDuktape_net_server_IPC_WriteCompletionEvent(ILibProcessPipe_Pipe sender, void *user, DWORD errorCode, int bytesWritten)
|
||||
{
|
||||
if (!ILibMemory_CanaryOK(user) || errorCode != 0) { return; }
|
||||
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user;
|
||||
duk_idx_t top = duk_get_top(winIPC->ctx);
|
||||
|
||||
duk_push_heapptr(winIPC->ctx, winIPC->mSocket); // [obj]
|
||||
duk_get_prop_string(winIPC->ctx, -1, ILibDuktape_net_WindowsIPC_PendingArray); // [obj][array]
|
||||
duk_get_prop_string(winIPC->ctx, -1, "shift"); // [obj][array][shift]
|
||||
duk_dup(winIPC->ctx, -2); // [obj][array][shift][this]
|
||||
if (duk_pcall_method(winIPC->ctx, 0) != 0) // [obj][array][buffer]
|
||||
{
|
||||
ILibDuktape_Process_UncaughtExceptionEx(winIPC->ctx, "Internal Error: net.socket.ipc.writeCompletionEvent");
|
||||
duk_set_top(winIPC->ctx, top); // ...
|
||||
return;
|
||||
}
|
||||
duk_pop(winIPC->ctx); // [obj][array]
|
||||
if (duk_get_length(winIPC->ctx, -1) > 0)
|
||||
{
|
||||
// Still pending Writes
|
||||
duk_get_prop_index(winIPC->ctx, -1, 0); // [obj][array][buffer]
|
||||
duk_size_t bufLen;
|
||||
char *buf = (char*)Duktape_GetBuffer(winIPC->ctx, -1, &bufLen);
|
||||
duk_set_top(winIPC->ctx, top); // ...
|
||||
ILibProcessPipe_Pipe_WriteEx(winIPC->mPipe, buf, (int)bufLen, winIPC, ILibDuktape_net_server_IPC_WriteCompletionEvent);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No more pending writes, so we can emit drain
|
||||
duk_set_top(winIPC->ctx, top); // ...
|
||||
ILibDuktape_DuplexStream_Ready(winIPC->ds);
|
||||
}
|
||||
}
|
||||
ILibTransport_DoneState ILibDuktape_net_server_IPC_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user)
|
||||
{
|
||||
if (!ILibMemory_CanaryOK(user)) { return(ILibTransport_DoneState_ERROR); }
|
||||
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user;
|
||||
if (!duk_ctx_is_alive(winIPC->ctx) || winIPC->mPipe == NULL) { return(ILibTransport_DoneState_ERROR); }
|
||||
if (!duk_ctx_is_alive(winIPC->ctx) || winIPC->mPipeHandle == NULL) { return(ILibTransport_DoneState_ERROR); }
|
||||
|
||||
duk_push_heapptr(winIPC->ctx, winIPC->mSocket); // [obj]
|
||||
duk_get_prop_string(winIPC->ctx, -1, ILibDuktape_net_WindowsIPC_PendingArray); // [obj][array]
|
||||
|
||||
|
||||
char *q = duk_push_fixed_buffer(winIPC->ctx, bufferLen); // [obj][array][buffer]
|
||||
duk_size_t len = duk_get_length(winIPC->ctx, -2);
|
||||
duk_put_prop_index(winIPC->ctx, -2, (duk_uarridx_t)len); // [obj][array]
|
||||
@@ -1015,7 +972,15 @@ ILibTransport_DoneState ILibDuktape_net_server_IPC_WriteSink(ILibDuktape_DuplexS
|
||||
if (len == 0)
|
||||
{
|
||||
// No Pending Writes
|
||||
return(ILibProcessPipe_Pipe_WriteEx(winIPC->mPipe, q, bufferLen, winIPC, ILibDuktape_net_server_IPC_WriteCompletionEvent));
|
||||
ILibTransport_DoneState ret = ILibChain_WriteEx(winIPC->mChain, winIPC->mPipeHandle, &(winIPC->write_overlapped), q, bufferLen, ILibDuktape_server_ipc_WriteSink, winIPC);
|
||||
if (ret != ILibTransport_DoneState_INCOMPLETE)
|
||||
{
|
||||
duk_push_heapptr(winIPC->ctx, winIPC->mSocket); // [obj]
|
||||
duk_get_prop_string(winIPC->ctx, -1, ILibDuktape_net_WindowsIPC_PendingArray); // [obj][array]
|
||||
duk_array_shift(winIPC->ctx, -1); // [obj][array][val]
|
||||
duk_pop_3(winIPC->ctx); // ...
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
return(ILibTransport_DoneState_INCOMPLETE);
|
||||
@@ -1025,10 +990,10 @@ void ILibDuktape_net_server_IPC_EndSink(ILibDuktape_DuplexStream *stream, void *
|
||||
if (!ILibMemory_CanaryOK(user)) { return; }
|
||||
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user;
|
||||
|
||||
//if (ILibProcessPipe_Pipe_CancelEx(winIPC->mPipe) == 0)
|
||||
//{
|
||||
ILibProcessPipe_FreePipe(winIPC->mPipe);
|
||||
winIPC->mPipe = NULL; winIPC->mPipeHandle = NULL;
|
||||
if (winIPC->mPipeHandle != NULL) { CloseHandle(winIPC->mPipeHandle); winIPC->mPipeHandle = NULL; }
|
||||
if (winIPC->read_overlapped.hEvent != NULL) { CloseHandle(winIPC->read_overlapped.hEvent); winIPC->read_overlapped.hEvent = NULL; }
|
||||
if (winIPC->write_overlapped.hEvent != NULL) { CloseHandle(winIPC->write_overlapped.hEvent); winIPC->write_overlapped.hEvent = NULL; }
|
||||
|
||||
if (winIPC->mServer != NULL)
|
||||
{
|
||||
// Server IPC, so we can create a new Instance, and listen for a connection
|
||||
@@ -1041,20 +1006,29 @@ void ILibDuktape_net_server_IPC_EndSink(ILibDuktape_DuplexStream *stream, void *
|
||||
duk_get_prop_string(ctx, -1, ILibDuktape_SERVER2LISTENOPTIONS); // [listen][this][options]
|
||||
duk_pcall_method(ctx, 1); duk_pop(ctx); // ...
|
||||
}
|
||||
//}
|
||||
}
|
||||
duk_ret_t ILibDuktape_net_server_IPC_ConnectSink_Finalizer(duk_context *ctx)
|
||||
{
|
||||
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)Duktape_GetBufferProperty(ctx, 0, ILibDuktape_net_WindowsIPC_Buffer);
|
||||
if (winIPC != NULL)
|
||||
{
|
||||
if (winIPC->mPipe != NULL && winIPC->mPipeHandle != NULL)
|
||||
if (winIPC->mPipeHandle != NULL)
|
||||
{
|
||||
// It's ok to do this, becuase the CancelEx happens on the same thread, and the completion routine will use an APC Queue, so the Canary will fail before it tries to deref
|
||||
//ILibProcessPipe_Pipe_CancelEx(winIPC->mPipe);
|
||||
ILibProcessPipe_FreePipe(winIPC->mPipe);
|
||||
winIPC->mPipe = NULL; winIPC->mPipeHandle = NULL;
|
||||
CloseHandle(winIPC->mPipeHandle);
|
||||
winIPC->mPipeHandle = NULL;
|
||||
}
|
||||
if (winIPC->read_overlapped.hEvent != NULL)
|
||||
{
|
||||
CloseHandle(winIPC->read_overlapped.hEvent);
|
||||
winIPC->read_overlapped.hEvent = NULL;
|
||||
}
|
||||
if (winIPC->write_overlapped.hEvent != NULL)
|
||||
{
|
||||
CloseHandle(winIPC->write_overlapped.hEvent);
|
||||
winIPC->write_overlapped.hEvent = NULL;
|
||||
}
|
||||
|
||||
if (winIPC->buffer != NULL) { free(winIPC->buffer); }
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
@@ -1064,6 +1038,7 @@ BOOL ILibDuktape_net_server_IPC_ConnectSink(void *chain, HANDLE event, ILibWaitH
|
||||
if (ILibMemory_CanaryOK(user) && status == ILibWaitHandle_ErrorStatus_NONE)
|
||||
{
|
||||
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user;
|
||||
winIPC->clientConnected = TRUE;
|
||||
ILibDuktape_EventEmitter_SetupEmit(winIPC->ctx, winIPC->mServer, "connection"); // [emit][this][connection]
|
||||
duk_push_object(winIPC->ctx); // [emit][this][connection][socket]
|
||||
ILibDuktape_WriteID(winIPC->ctx, "net.socket.ipc");
|
||||
@@ -1076,8 +1051,9 @@ BOOL ILibDuktape_net_server_IPC_ConnectSink(void *chain, HANDLE event, ILibWaitH
|
||||
duk_push_array(winIPC->ctx); duk_put_prop_string(winIPC->ctx, -2, ILibDuktape_net_WindowsIPC_PendingArray);
|
||||
winIPC->mSocket = duk_get_heapptr(winIPC->ctx, -1);
|
||||
winIPC->ds = ILibDuktape_DuplexStream_InitEx(winIPC->ctx, ILibDuktape_net_server_IPC_WriteSink, ILibDuktape_net_server_IPC_EndSink, ILibDuktape_net_server_IPC_PauseSink, ILibDuktape_net_server_IPC_ResumeSink, ILibDuktape_net_server_IPC_unshiftSink, winIPC);
|
||||
winIPC->mPipe = ILibProcessPipe_Pipe_CreateFromExisting(winIPC->manager, winIPC->mPipeHandle, ILibProcessPipe_Pipe_ReaderHandleType_Overlapped);
|
||||
winIPC->ds->readableStream->paused = 1;
|
||||
winIPC->paused = 1;
|
||||
|
||||
ILibDuktape_EventEmitter_AddHook(ILibDuktape_EventEmitter_GetEmitter(winIPC->ctx, -1), "data", ILibDuktape_net_socket_ipc_dataHookCallback);
|
||||
ILibDuktape_EventEmitter_AddHook(ILibDuktape_EventEmitter_GetEmitter(winIPC->ctx, -1), "end", ILibDuktape_net_socket_ipc_dataHookCallback);
|
||||
|
||||
@@ -1191,12 +1167,14 @@ duk_ret_t ILibDuktape_net_server_listen(duk_context *ctx)
|
||||
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)Duktape_PushBuffer(ctx, sizeof(ILibDuktape_net_WindowsIPC));
|
||||
duk_put_prop_string(ctx, -2, ILibDuktape_net_WindowsIPC_Buffer);
|
||||
winIPC->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
winIPC->read_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
winIPC->write_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
winIPC->ctx = ctx;
|
||||
winIPC->mServer = duk_get_heapptr(ctx, -1);
|
||||
winIPC->mChain = Duktape_GetChain(ctx);
|
||||
winIPC->mChain = duk_ctx_chain(ctx);
|
||||
winIPC->clientConnected = FALSE;
|
||||
|
||||
duk_eval_string(ctx, "require('child_process');");
|
||||
winIPC->manager = (ILibProcessPipe_Manager)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Manager);
|
||||
duk_pop(ctx);
|
||||
|
||||
if (Duktape_GetBooleanProperty(ctx, 0, "writableAll", 0) != 0)
|
||||
@@ -1235,7 +1213,6 @@ duk_ret_t ILibDuktape_net_server_listen(duk_context *ctx)
|
||||
}
|
||||
//printf("ConnectNamedPipe(%s)\n", ipc);
|
||||
ConnectNamedPipe(winIPC->mPipeHandle, &winIPC->overlapped);
|
||||
//ILibProcessPipe_WaitHandle_Add2(winIPC->manager, winIPC->overlapped.hEvent, winIPC, ILibDuktape_net_server_IPC_ConnectSink);
|
||||
ILibChain_AddWaitHandle(duk_ctx_chain(ctx), winIPC->overlapped.hEvent, -1, ILibDuktape_net_server_IPC_ConnectSink, winIPC);
|
||||
|
||||
if (pIPC_SA != NULL) { LocalFree(IPC_ACL); }
|
||||
@@ -1381,7 +1358,7 @@ duk_ret_t ILibDuktape_net_server_close(duk_context *ctx)
|
||||
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)Duktape_GetBufferProperty(ctx, -1, ILibDuktape_net_WindowsIPC_Buffer);
|
||||
if (winIPC != NULL && winIPC->mPipeHandle != NULL)
|
||||
{
|
||||
if (winIPC->mPipe == NULL)
|
||||
if (winIPC->clientConnected == FALSE)
|
||||
{
|
||||
// Listening
|
||||
DisconnectNamedPipe(winIPC->mPipeHandle);
|
||||
|
||||
@@ -2091,7 +2091,7 @@ int ILibChain_WindowsSelect(void *chain, fd_set *readset, fd_set *writeset, fd_s
|
||||
}
|
||||
return(slct);
|
||||
}
|
||||
void ILibChain_SetupWindowsWaitObject(HANDLE* waitList, int *waitListCount, struct timeval *tv, DWORD *timeout, fd_set *readset, fd_set *writeset, fd_set *errorset, ILibLinkedList handleList)
|
||||
void ILibChain_SetupWindowsWaitObject(HANDLE* waitList, int *waitListCount, struct timeval *tv, DWORD *timeout, fd_set *readset, fd_set *writeset, fd_set *errorset, ILibLinkedList handleList, HANDLE **onlyHandles)
|
||||
{
|
||||
HANDLE selectHandles[FD_SETSIZE];
|
||||
memset(selectHandles, 0, sizeof(selectHandles));
|
||||
@@ -2101,7 +2101,7 @@ void ILibChain_SetupWindowsWaitObject(HANDLE* waitList, int *waitListCount, stru
|
||||
*waitListCount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
int chkIndex;
|
||||
void *node;
|
||||
struct timeval currentTime;
|
||||
struct timeval expirationTime;
|
||||
@@ -2151,6 +2151,22 @@ void ILibChain_SetupWindowsWaitObject(HANDLE* waitList, int *waitListCount, stru
|
||||
node = ILibLinkedList_GetNode_Head(handleList);
|
||||
while (node != NULL)
|
||||
{
|
||||
if (onlyHandles != NULL)
|
||||
{
|
||||
for (chkIndex = 0; onlyHandles[chkIndex] != NULL; ++chkIndex)
|
||||
{
|
||||
if ((HANDLE)ILibLinkedList_GetDataFromNode(node) == onlyHandles[chkIndex])
|
||||
{
|
||||
chkIndex = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (chkIndex != -1)
|
||||
{
|
||||
node = ILibLinkedList_GetNextNode(node);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
i = x++;
|
||||
if (waitList[i] != NULL && waitList[ILibChain_HandleInfoIndex(i)] == NULL)
|
||||
{
|
||||
@@ -2184,7 +2200,11 @@ ILibChain_ContinuationStates ILibChain_GetContinuationState(void *chain)
|
||||
{
|
||||
return(((ILibBaseChain*)chain)->continuationState);
|
||||
}
|
||||
#ifdef WIN32
|
||||
ILibExportMethod void ILibChain_Continue(void *Chain, ILibChain_Link **modules, int moduleCount, int maxTimeout, HANDLE **handles)
|
||||
#else
|
||||
ILibExportMethod void ILibChain_Continue(void *Chain, ILibChain_Link **modules, int moduleCount, int maxTimeout)
|
||||
#endif
|
||||
{
|
||||
ILibBaseChain *chain = (ILibBaseChain*)Chain;
|
||||
ILibChain_Link_Hook *nodeHook;
|
||||
@@ -2207,6 +2227,11 @@ ILibExportMethod void ILibChain_Continue(void *Chain, ILibChain_Link **modules,
|
||||
gettimeofday(&startTime, NULL);
|
||||
ILibRemoteLogging_printf(ILibChainGetLogger(chain), ILibRemoteLogging_Modules_Microstack_Generic, ILibRemoteLogging_Flags_VerbosityLevel_1, "ContinueChain...");
|
||||
|
||||
#ifdef WIN32
|
||||
HANDLE currentHandle = chain->currentHandle;
|
||||
ILibChain_WaitHandleInfo* currentInfo = chain->currentInfo;
|
||||
#endif
|
||||
|
||||
while (root->TerminateFlag == 0 && root->continuationState == ILibChain_ContinuationState_CONTINUE)
|
||||
{
|
||||
if (maxTimeout > 0)
|
||||
@@ -2285,7 +2310,7 @@ ILibExportMethod void ILibChain_Continue(void *Chain, ILibChain_Link **modules,
|
||||
int x = 0;
|
||||
DWORD waitTimeout = 0;
|
||||
|
||||
ILibChain_SetupWindowsWaitObject(chain->WaitHandles, &x, &tv, &waitTimeout, &readset, &writeset, &errorset, chain->auxSelectHandles);
|
||||
ILibChain_SetupWindowsWaitObject(chain->WaitHandles, &x, &tv, &waitTimeout, &readset, &writeset, &errorset, chain->auxSelectHandles, handles);
|
||||
slct = ILibChain_WindowsSelect(chain, &readset, &writeset, &errorset, chain->WaitHandles, x, waitTimeout);
|
||||
#else
|
||||
slct = select(FD_SETSIZE, &readset, &writeset, &errorset, &tv);
|
||||
@@ -2351,6 +2376,10 @@ ILibExportMethod void ILibChain_Continue(void *Chain, ILibChain_Link **modules,
|
||||
|
||||
ILibRemoteLogging_printf(ILibChainGetLogger(chain), ILibRemoteLogging_Modules_Microstack_Generic, ILibRemoteLogging_Flags_VerbosityLevel_1, "ContinueChain...Ending...");
|
||||
root->node = currentNode;
|
||||
#ifdef WIN32
|
||||
root->currentHandle = currentHandle;
|
||||
root->currentInfo = currentInfo;
|
||||
#endif
|
||||
}
|
||||
|
||||
ILibExportMethod void ILibChain_EndContinue(void *chain)
|
||||
@@ -2991,18 +3020,48 @@ void *ILibChain_GetObjectForDescriptor(void *chain, int fd)
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
BOOL ILibChain_ReadEx_Sink(void *chain, HANDLE h, ILibWaitHandle_ErrorStatus status, void *user)
|
||||
BOOL ILibChain_WriteEx_Sink(void *chain, HANDLE h, ILibWaitHandle_ErrorStatus status, void *user)
|
||||
{
|
||||
ILibChain_ReadEx_data *data = (ILibChain_ReadEx_data*)user;
|
||||
DWORD bytesRead = 0;
|
||||
ILibChain_WriteEx_data *data = (ILibChain_WriteEx_data*)user;
|
||||
DWORD bytesWritten = 0;
|
||||
|
||||
if (GetOverlappedResult(data->fileHandle, data->p, &bytesRead, FALSE) && bytesRead > 0)
|
||||
if (GetOverlappedResult(data->fileHandle, data->p, &bytesWritten, FALSE) && bytesWritten > 0)
|
||||
{
|
||||
if (data->handler != NULL) { data->handler(chain, data->fileHandle, ILibWaitHandle_ErrorStatus_NONE, data->buffer, bytesRead, data->user); }
|
||||
data->bytesLeft -= (int)bytesWritten;
|
||||
data->totalWritten += (int)bytesWritten;
|
||||
data->buffer = data->buffer + bytesWritten;
|
||||
if (data->bytesLeft == 0)
|
||||
{
|
||||
// Done Writing
|
||||
if (data->handler != NULL) { data->handler(chain, data->fileHandle, ILibWaitHandle_ErrorStatus_NONE, data->totalWritten, data->user); }
|
||||
ILibMemory_Free(data);
|
||||
return(FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// More Data to write
|
||||
BOOL ret = FALSE;
|
||||
switch (ILibChain_WriteEx(chain, h, data->p, data->buffer, data->bytesLeft, ILibChain_WriteEx_Sink, data))
|
||||
{
|
||||
case ILibTransport_DoneState_COMPLETE:
|
||||
data->totalWritten += data->bytesLeft;
|
||||
data->bytesLeft = 0;
|
||||
if (data->handler != NULL) { data->handler(chain, data->fileHandle, ILibWaitHandle_ErrorStatus_NONE, data->totalWritten, data->user); }
|
||||
ILibMemory_Free(data);
|
||||
ret = FALSE;
|
||||
break;
|
||||
case ILibTransport_DoneState_INCOMPLETE:
|
||||
ret = TRUE;
|
||||
case ILibTransport_DoneState_ERROR:
|
||||
if (data->handler != NULL) { data->handler(chain, data->fileHandle, ILibWaitHandle_ErrorStatus_IO_ERROR, 0, data->user); }
|
||||
ILibMemory_Free(data);
|
||||
ret = FALSE;
|
||||
break;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetLastError() == ERROR_IO_PENDING)
|
||||
{
|
||||
@@ -3010,6 +3069,35 @@ BOOL ILibChain_ReadEx_Sink(void *chain, HANDLE h, ILibWaitHandle_ErrorStatus sta
|
||||
return(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ERROR
|
||||
if (data->handler != NULL) { data->handler(chain, data->fileHandle, ILibWaitHandle_ErrorStatus_IO_ERROR, 0, data->user); }
|
||||
ILibMemory_Free(data);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
BOOL ILibChain_ReadEx_Sink(void *chain, HANDLE h, ILibWaitHandle_ErrorStatus status, void *user)
|
||||
{
|
||||
ILibChain_ReadEx_data *data = (ILibChain_ReadEx_data*)user;
|
||||
DWORD bytesRead = 0;
|
||||
DWORD err;
|
||||
|
||||
if (GetOverlappedResult(data->fileHandle, data->p, &bytesRead, FALSE) && bytesRead > 0)
|
||||
{
|
||||
if (data->handler != NULL) { data->handler(chain, data->fileHandle, ILibWaitHandle_ErrorStatus_NONE, data->buffer, bytesRead, data->user); }
|
||||
ILibMemory_Free(data);
|
||||
return(FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((err=GetLastError()) == ERROR_IO_PENDING)
|
||||
{
|
||||
// Still pending, so wait for another callback
|
||||
return(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ERROR
|
||||
if (data->handler != NULL) { data->handler(chain, data->fileHandle, ILibWaitHandle_ErrorStatus_IO_ERROR, data->buffer, 0, data->user); }
|
||||
@@ -3018,6 +3106,37 @@ BOOL ILibChain_ReadEx_Sink(void *chain, HANDLE h, ILibWaitHandle_ErrorStatus sta
|
||||
}
|
||||
}
|
||||
}
|
||||
ILibTransport_DoneState ILibChain_WriteEx(void *chain, HANDLE h, OVERLAPPED *p, char *buffer, int bufferLen, ILibChain_WriteEx_Handler handler, void *user)
|
||||
{
|
||||
int e = 0;
|
||||
if (!WriteFile(h, buffer, (DWORD)bufferLen, NULL, p))
|
||||
{
|
||||
if ((e = GetLastError()) == ERROR_IO_PENDING)
|
||||
{
|
||||
// Completing Asynchronously
|
||||
ILibChain_WriteEx_data *state = (ILibChain_WriteEx_data*)ILibMemory_SmartAllocate(sizeof(ILibChain_WriteEx_data));
|
||||
state->buffer = buffer;
|
||||
state->bytesLeft = bufferLen;
|
||||
state->totalWritten = 0;
|
||||
state->p = p;
|
||||
state->handler = handler;
|
||||
state->fileHandle = h;
|
||||
state->user = user;
|
||||
ILibChain_AddWaitHandle(chain, p->hEvent, -1, ILibChain_WriteEx_Sink, state);
|
||||
return(ILibTransport_DoneState_INCOMPLETE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// IO Error
|
||||
return(ILibTransport_DoneState_ERROR);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write Completed
|
||||
return(ILibTransport_DoneState_COMPLETE);
|
||||
}
|
||||
}
|
||||
void ILibChain_ReadEx(void *chain, HANDLE h, OVERLAPPED *p, char *buffer, int bufferLen, ILibChain_ReadEx_Handler handler, void *user)
|
||||
{
|
||||
DWORD bytesRead = 0;
|
||||
@@ -3080,26 +3199,30 @@ void ILibChain_AddWaitHandle(void *chain, HANDLE h, int msTIMEOUT, ILibChain_Wai
|
||||
return;
|
||||
}
|
||||
|
||||
ILibChain_WaitHandleInfo *info = NULL;
|
||||
|
||||
if (((ILibBaseChain*)chain)->currentHandle != h)
|
||||
{
|
||||
void *node = ILibLinkedList_AddTail(((ILibBaseChain*)chain)->auxSelectHandles, h);
|
||||
ILibChain_WaitHandleInfo *info = (ILibChain_WaitHandleInfo*)ILibMemory_Extra(node);
|
||||
info = (ILibChain_WaitHandleInfo*)ILibMemory_Extra(node);
|
||||
info->node = node;
|
||||
ILibForceUnBlockChain(chain);
|
||||
}
|
||||
else
|
||||
{
|
||||
((ILibBaseChain*)chain)->currentHandle = NULL;
|
||||
info = ((ILibBaseChain*)chain)->currentInfo;
|
||||
}
|
||||
if (info != NULL)
|
||||
{
|
||||
info->handler = handler;
|
||||
info->user = user;
|
||||
info->node = node;
|
||||
if (msTIMEOUT != INFINITE && msTIMEOUT >= 0)
|
||||
{
|
||||
ILibGetTimeOfDay(&(info->expiration));
|
||||
info->expiration.tv_sec += (long)(msTIMEOUT / 1000);
|
||||
info->expiration.tv_usec += ((msTIMEOUT % 1000) * 1000);
|
||||
}
|
||||
ILibForceUnBlockChain(chain);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We are trying to add ourselves, so we can optimize by not deleting, intead of adding new
|
||||
((ILibBaseChain*)chain)->currentHandle = NULL;
|
||||
if (((ILibBaseChain*)chain)->currentInfo->user != user) { ((ILibBaseChain*)chain)->currentInfo->user = user; }
|
||||
}
|
||||
}
|
||||
void __stdcall ILibChain_RemoveWaitHandle_APC(ULONG_PTR u)
|
||||
@@ -3114,7 +3237,10 @@ void __stdcall ILibChain_RemoveWaitHandle_APC(ULONG_PTR u)
|
||||
// We found the HANDLE, so if we remove the HANDLE from the list, and
|
||||
// set the unblock flag, we'll be good to go
|
||||
//
|
||||
if (chain->currentHandle == h) { chain->currentHandle = NULL; chain->currentInfo = NULL; }
|
||||
if (chain->currentHandle == h)
|
||||
{
|
||||
chain->currentHandle = NULL; chain->currentInfo = NULL;
|
||||
}
|
||||
ILibLinkedList_Remove(node);
|
||||
chain->UnblockFlag = 1;
|
||||
}
|
||||
@@ -3292,7 +3418,7 @@ ILibExportMethod void ILibStartChain(void *Chain)
|
||||
int x = 0;
|
||||
DWORD waitTimeout = 0;
|
||||
|
||||
ILibChain_SetupWindowsWaitObject(chain->WaitHandles, &x, &tv, &waitTimeout, &readset, &writeset, &errorset, chain->auxSelectHandles);
|
||||
ILibChain_SetupWindowsWaitObject(chain->WaitHandles, &x, &tv, &waitTimeout, &readset, &writeset, &errorset, chain->auxSelectHandles, NULL);
|
||||
slct = ILibChain_WindowsSelect(chain, &readset, &writeset, &errorset, chain->WaitHandles, x, waitTimeout);
|
||||
#else
|
||||
slct = select(FD_SETSIZE, &readset, &writeset, &errorset, &tv);
|
||||
|
||||
@@ -974,7 +974,9 @@ int ILibIsRunningOnChainThread(void* chain);
|
||||
void *ILibChain_GetObjectForDescriptor(void *chain, int fd);
|
||||
char *ILibChain_GetMetaDataFromDescriptorSet(void *chain, fd_set *inr, fd_set *inw, fd_set *ine);
|
||||
#ifdef WIN32
|
||||
typedef void(*ILib_GenericReadHandler)(char *buffer, int bufferLen, int* bytesConsumed, void* user1, void *user2);
|
||||
typedef BOOL(*ILibChain_ReadEx_Handler)(void *chain, HANDLE h, ILibWaitHandle_ErrorStatus status, char *buffer, int bytesRead, void* user);
|
||||
typedef BOOL(*ILibChain_WriteEx_Handler)(void *chain, HANDLE h, ILibWaitHandle_ErrorStatus status, int bytesWritten, void* user);
|
||||
typedef struct ILibChain_ReadEx_data
|
||||
{
|
||||
char *buffer;
|
||||
@@ -983,9 +985,20 @@ int ILibIsRunningOnChainThread(void* chain);
|
||||
OVERLAPPED *p;
|
||||
void *user;
|
||||
}ILibChain_ReadEx_data;
|
||||
typedef struct ILibChain_WriteEx_data
|
||||
{
|
||||
ILibChain_WriteEx_Handler handler;
|
||||
char *buffer;
|
||||
int bytesLeft;
|
||||
int totalWritten;
|
||||
HANDLE fileHandle;
|
||||
OVERLAPPED *p;
|
||||
void *user;
|
||||
}ILibChain_WriteEx_data;
|
||||
void ILibChain_AddWaitHandle(void *chain, HANDLE h, int msTIMEOUT, ILibChain_WaitHandleHandler handler, void *user);
|
||||
void ILibChain_RemoveWaitHandle(void *chain, HANDLE h);
|
||||
void ILibChain_ReadEx(void *chain, HANDLE h, OVERLAPPED *p, char *buffer, int bufferLen, ILibChain_ReadEx_Handler handler, void *user);
|
||||
ILibTransport_DoneState ILibChain_WriteEx(void *chain, HANDLE h, OVERLAPPED *p, char *buffer, int bufferLen, ILibChain_WriteEx_Handler handler, void *user);
|
||||
#define tv2LTtv1(ptv1, ptv2) ((ptv2)->tv_sec < (ptv1)->tv_sec || ((ptv2)->tv_sec == (ptv1)->tv_sec && (ptv2)->tv_usec < (ptv1)->tv_usec))
|
||||
#define tv2LTEtv1(ptv1, ptv2) (tv2LTtv1(ptv2,ptv1) || ((ptv2)->tv_sec == (ptv1)->tv_sec && (ptv2)->tv_usec <= (ptv1)->tv_usec))
|
||||
#define tvnonzero(ptv) ((ptv)->tv_sec != 0 || (ptv)->tv_usec != 0)
|
||||
@@ -993,7 +1006,11 @@ int ILibIsRunningOnChainThread(void* chain);
|
||||
|
||||
ILibExportMethod void ILibStartChain(void *chain);
|
||||
ILibExportMethod void ILibStopChain(void *chain);
|
||||
#ifdef WIN32
|
||||
ILibExportMethod void ILibChain_Continue(void *chain, ILibChain_Link **modules, int moduleCount, int maxTimeout, HANDLE **handles);
|
||||
#else
|
||||
ILibExportMethod void ILibChain_Continue(void *chain, ILibChain_Link **modules, int moduleCount, int maxTimeout);
|
||||
#endif
|
||||
ILibExportMethod void ILibChain_EndContinue(void *chain);
|
||||
ILibChain_ContinuationStates ILibChain_GetContinuationState(void *chain);
|
||||
#define ILibChain_FreeLink(link) ((ILibChain_Link*)link)->RESERVED = 0xFFFFFFFF;free(link);
|
||||
|
||||
@@ -1318,6 +1318,16 @@ void ILibProcessPipe_Process_AddHandlers(ILibProcessPipe_Process module, int buf
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef WIN32
|
||||
void ILibProcessPipe_Process_GetWaitHandles(ILibProcessPipe_Process p, HANDLE *hProcess, HANDLE *read, HANDLE *write, HANDLE *error)
|
||||
{
|
||||
ILibProcessPipe_Process_Object* j = (ILibProcessPipe_Process_Object*)p;
|
||||
*hProcess = j->hProcess;
|
||||
*read = j->stdOut->mOverlapped->hEvent;
|
||||
*error = j->stdErr->mOverlapped->hEvent;
|
||||
*write = j->stdIn->mOverlapped->hEvent;
|
||||
}
|
||||
#endif
|
||||
void ILibProcessPipe_Pipe_Close(ILibProcessPipe_Pipe po)
|
||||
{
|
||||
ILibProcessPipe_PipeObject* pipeObject = (ILibProcessPipe_PipeObject*)po;
|
||||
|
||||
@@ -86,6 +86,9 @@ void ILibProcessPipe_Process_RemoveHandlers(ILibProcessPipe_Process module);
|
||||
void ILibProcessPipe_Process_UpdateUserObject(ILibProcessPipe_Process module, void *userObj);
|
||||
ILibTransport_DoneState ILibProcessPipe_Process_WriteStdIn(ILibProcessPipe_Process p, char* buffer, int bufferLen, ILibTransport_MemoryOwnership ownership);
|
||||
void ILibProcessPipe_Process_CloseStdIn(ILibProcessPipe_Process p);
|
||||
#ifdef WIN32
|
||||
void ILibProcessPipe_Process_GetWaitHandles(ILibProcessPipe_Process p, HANDLE *hProcess, HANDLE *read, HANDLE *write, HANDLE *error);
|
||||
#endif
|
||||
|
||||
void ILibProcessPipe_Pipe_Close(ILibProcessPipe_Pipe po);
|
||||
void ILibProcessPipe_Pipe_Pause(ILibProcessPipe_Pipe pipeObject);
|
||||
|
||||
Reference in New Issue
Block a user