1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2025-12-06 00:13:33 +00:00

Improved agent that can update the MeshCentral1 agent

This commit is contained in:
Ylian Saint-Hilaire
2017-11-09 16:07:39 -08:00
parent 34e09c2304
commit becf71557f
36 changed files with 1520 additions and 208 deletions

205
Debug/AMT.js Normal file
View File

@@ -0,0 +1,205 @@
var http = require('http');
var digest = require('http-digest').create("admin", "P@ssw0rd");
console.log("Starting AMT Test");
digest.http = require('http');
//console.log("First Test: HTTP/GET on '/'");
//var req = digest.request({ protocol: "http:", method: "GET", host: "172.16.2.249", path: "/", port: 16992 }, OnGet1);
//req.end();
//console.log('First Test: POST /wsman');
//WSManTest();
console.log('First Test: POST /wsman, [immediate]');
WSManTest_Immediate();
function OnGet1(imsg)
{
if(imsg.statusCode == 303)
{
console.log("...SUCCESS!");
console.log("Next Test: Redirect to '" + imsg.header['Location'] + "'");
req = digest.request({ protocol: "http:", method: "GET", host: "172.16.2.249", path: imsg.header['Location'], port: 16992 }, OnGet2);
req.end();
}
else
{
console.log("...FAILED!");
}
}
function OnGet2(imsg)
{
if (imsg.statusCode == 200)
{
console.log("...SUCCESS!");
console.log("...Reading body of message");
imsg.on('end', function ()
{
console.log("...Finished");
console.log("Next Test: '/index.htm'");
req = digest.request({ protocol: "http:", method: "GET", host: "172.16.2.249", path: "/index.htm", port: 16992 }, OnGet3);
req.end();
});
}
else
{
console.log("...FAILED, status code was: " + imsg.statusCode);
}
}
function OnGet3(imsg)
{
if (imsg.statusCode == 200)
{
console.log("...SUCCESS!");
console.log("Next Test: 'POST /wsman'");
WSManTest();
}
}
function WSManTest()
{
req = digest.request({ protocol: "http:", method: "POST", host: "172.16.2.249", path: "/wsman", port: 16992, headers: { Expect: '100-Continue' }, timeout: 2000 });
req.on('continue', WSManTest_Continue);
req.on('timeout', WSManTest_Timeout);
req.on('response', WSManTest_Response);
}
function WSManTest_Immediate()
{
req = digest.request({ protocol: "http:", method: "POST", host: "172.16.2.249", path: "/wsman", port: 16992 });
req.on('response', WSManTest_Response);
var xml = 'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48RW52ZWxvcGUgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeG1sbnM6eHNkPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIgeG1sbnM6YT0iaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNC8wOC9hZGRyZXNzaW5nIiB4bWxuczp3PSJodHRwOi8vc2NoZW1hcy5kbXRmLm9yZy93YmVtL3dzbWFuLzEvd3NtYW4ueHNkIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMy8wNS9zb2FwLWVudmVsb3BlIiA+PEhlYWRlcj48YTpBY3Rpb24+aHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNC8wOS90cmFuc2Zlci9HZXQ8L2E6QWN0aW9uPjxhOlRvPi93c21hbjwvYTpUbz48dzpSZXNvdXJjZVVSST5odHRwOi8vc2NoZW1hcy5kbXRmLm9yZy93YmVtL3dzY2ltLzEvY2ltLXNjaGVtYS8yL0NJTV9Db21wdXRlclN5c3RlbVBhY2thZ2U8L3c6UmVzb3VyY2VVUkk+PGE6TWVzc2FnZUlEPjQ8L2E6TWVzc2FnZUlEPjxhOlJlcGx5VG8+PGE6QWRkcmVzcz5odHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA0LzA4L2FkZHJlc3Npbmcvcm9sZS9hbm9ueW1vdXM8L2E6QWRkcmVzcz48L2E6UmVwbHlUbz48dzpPcGVyYXRpb25UaW1lb3V0PlBUNjBTPC93Ok9wZXJhdGlvblRpbWVvdXQ+PC9IZWFkZXI+PEJvZHkgLz48L0VudmVsb3BlPg==';
var b = Buffer.from(xml, 'base64');
req.write(b);
req.end();
}
function WSManTest_Continue()
{
console.log("Got Continue!");
}
function WSManTest_Timeout()
{
console.log("Timeout waiting for 100 Continue... Sending body anyways...");
var xml = 'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48RW52ZWxvcGUgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeG1sbnM6eHNkPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIgeG1sbnM6YT0iaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNC8wOC9hZGRyZXNzaW5nIiB4bWxuczp3PSJodHRwOi8vc2NoZW1hcy5kbXRmLm9yZy93YmVtL3dzbWFuLzEvd3NtYW4ueHNkIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMy8wNS9zb2FwLWVudmVsb3BlIiA+PEhlYWRlcj48YTpBY3Rpb24+aHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNC8wOS90cmFuc2Zlci9HZXQ8L2E6QWN0aW9uPjxhOlRvPi93c21hbjwvYTpUbz48dzpSZXNvdXJjZVVSST5odHRwOi8vc2NoZW1hcy5kbXRmLm9yZy93YmVtL3dzY2ltLzEvY2ltLXNjaGVtYS8yL0NJTV9Db21wdXRlclN5c3RlbVBhY2thZ2U8L3c6UmVzb3VyY2VVUkk+PGE6TWVzc2FnZUlEPjQ8L2E6TWVzc2FnZUlEPjxhOlJlcGx5VG8+PGE6QWRkcmVzcz5odHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA0LzA4L2FkZHJlc3Npbmcvcm9sZS9hbm9ueW1vdXM8L2E6QWRkcmVzcz48L2E6UmVwbHlUbz48dzpPcGVyYXRpb25UaW1lb3V0PlBUNjBTPC93Ok9wZXJhdGlvblRpbWVvdXQ+PC9IZWFkZXI+PEJvZHkgLz48L0VudmVsb3BlPg==';
var b = Buffer.from(xml, 'base64');
this.write(b);
this.end();
}
function WSManTest_Response(imsg)
{
imsg.on('data', function (chunk) { console.log(chunk); });
}
//var req = digest.request({ protocol: "ws:", method: "GET", host: "127.0.0.1", path: "/", port: 9093 }, function (imsg) { console.log(imsg.statusCode == 200 ? "SUCCESS!" : "FAIL!"); });
//var req = http.request({ protocol: "http:", method: "POST", host: "127.0.0.1", path: "/", port: 9093, headers: { Expect: '100-Continue' } }, function (imsg) { console.log(imsg.statusCode == 200 ? "SUCCESS!" : "FAIL!"); });
//var req = digest.request({ protocol: "http:", method: "POST", host: "127.0.0.1", path: "/", port: 9093, headers: { Expect: '100-Continue' } }, function (imsg) { console.log(imsg.statusCode == 200 ? "SUCCESS!" : "FAIL!"); });
//req.on('upgrade', function (res, sk, h) { console.log("Upgraded to WebSocket!"); });
//req.on('error', function () { console.log("Error occured"); });
//req.on('continue', function () { console.log("Received Continue"); this.write("test"); this.end(); });
//function OnCheckContinue(imsg, resp)
//{
// console.log("Recevied: Expect-100 Continue");
// if (imsg.Digest_IsAuthenticated('www.meshcentral.com') == 1)
// {
// var uname = imsg.Digest_GetUsername();
// console.log("Digest Username was: " + uname);
// if (uname == 'bryan' && imsg.Digest_ValidatePassword('roe') == 1)
// {
// console.log("Validated");
// imsg.on('data', function (chunk) { console.log('Received: ' + chunk.toString()); });
// imsg.on('end', function () { console.log('Received Complete'); });
// resp.writeContinue();
// }
// else
// {
// console.log("Bad Username/Password");
// resp.statusCode = "500";
// resp.statusMessage = "Error";
// resp.end();
// }
// }
// else
// {
// console.log("Sending Unauthorized");
// imsg.Digest_SendUnauthorized('www.meshcentral.com', 'oops');
// }
//}
//function OnCheckContinue_NoDigest(imsg, resp)
//{
// console.log("Recevied: Expect-100 Continue");
// imsg.on('data', function (chunk) { console.log('Received: ' + chunk.toString()); });
// imsg.on('end', function () { console.log('Received Complete'); });
// resp.writeContinue();
//}
//function OnServerUpgrade(imsg, sck, head)
//{
// if(imsg.Digest_IsAuthenticated('www.meshcentral.com')==1)
// {
// var uname = imsg.Digest_GetUsername();
// console.log("Digest Username was: " + uname);
// if(uname == 'bryan' && imsg.Digest_ValidatePassword('roe')==1)
// {
// console.log("Upgrading to WebSocket");
// sck.upgradeWebSocket();
// }
// else
// {
// console.log("Bad Username/Password");
// sck.end();
// }
// }
// else
// {
// console.log("Sending Unauthorized");
// imsg.Digest_SendUnauthorized('www.meshcentral.com', 'oops');
// }
//}
//function onVerifyServer(clientName, certs) {
// console.log("Server Name = " + clientName + "\n");
// for (var i = 0; i < certs.length; ++i) {
// console.log(" Fingerprint = " + certs[i].fingerprint + "\n");
// }
// //throw ("Not Valid");
//}
//function onVerifyClient(clientName, certs)
//{
// console.log("Client Name = " + clientName + "\n");
// for (var i = 0; i < certs.length; ++i) {
// console.log(" Fingerprint = " + certs[i].fingerprint + "\n");
// }
// //throw ("Not Valid");
//}
//function onVerify(serverName, certs)
//{
// console.log("ServerName = " + serverName + "\n");
// for (var i = 0; i < certs.length;++i)
// {
// console.log(" Fingerprint = " + certs[i].fingerprint + "\n");
// }
// //throw ("Not Valid");
//}
//function OnRequest(req, res)
//{
// console.log("Received Request for: " + req.url);
//}

27
Debug/ChildProcessTest.js Normal file
View File

@@ -0,0 +1,27 @@
var child = require('child_process');
var childProcess = null;
if (process.platform == 'win32')
{
childProcess = child.execFile(process.env['windir'] + '\\system32\\cmd.exe', ['/c', 'dir'], OnChild);
}
else if (process.platform == 'linux')
{
childProcess = child.execFile('/bin/sh', ['sh', '-c', 'ls'], OnChild);
}
if (childProcess != null)
{
console.log('PID = ' + childProcess.pid);
childProcess.stdout.on('data', function (chunk) { console.log(chunk.toString()); });
childProcess.on('exit', function (code, sig) { console.log("Process Exited with code: " + code.toString()); });
}
//for (var envkey in process.env)
//{
// console.log("Environment Variable: [" + envkey + "] = " + process.env[envkey]);
//}
function OnChild(err, stdErr, stdOut)
{
}

View File

@@ -4,11 +4,15 @@ var req = "";
var gtunnel = "";
var digest = require('http-digest').create("bryan", "roe");
console.log("Process.execPath = " + process.execPath);
console.log("Starting POST Digest Test");
server = http.createServer(OnRequest);
server.listen(9093);
console.log("Server Address", server._address());
server.on('upgrade', OnServerUpgrade);
server.on('checkContinue', OnCheckContinue);
//server.on('checkContinue', OnCheckContinue_NoDigest);

View File

@@ -39,6 +39,7 @@ SOURCES += microscript/ILibWebServer_Duktape.c microscript/ILibDuktape_SimpleDat
SOURCES += microscript/ILibDuktape_ProcessPipe.c microscript/ILibDuktape_fs.c microscript/ILibDuktape_SHA256.c microscript/ILibduktape_EventEmitter.c
SOURCES += microscript/ILibDuktape_EncryptionStream.c microscript/ILibDuktape_Polyfills.c microscript/ILibDuktape_Dgram.c
SOURCES += microscript/ILibDuktape_ScriptContainer.c microscript/ILibDuktape_MemoryStream.c microscript/ILibDuktape_NetworkMonitor.c
SOURCES += microscript/ILibDuktape_ChildProcess.c
# Mesh Agent core
SOURCES += meshcore/agentcore.c meshconsole/main.c meshcore/meshinfo.c

View File

@@ -31,6 +31,7 @@
<ClCompile Include="..\microscript\duktape.c" />
<ClCompile Include="..\microscript\ILibAsyncSocket_Duktape.c" />
<ClCompile Include="..\microscript\ILibDuktapeModSearch.c" />
<ClCompile Include="..\microscript\ILibDuktape_ChildProcess.c" />
<ClCompile Include="..\microscript\ILibDuktape_Debugger.c" />
<ClCompile Include="..\microscript\ILibDuktape_Dgram.c" />
<ClCompile Include="..\microscript\ILibDuktape_DuplexStream.c" />
@@ -91,6 +92,7 @@
<ClInclude Include="..\microscript\duk_config.h" />
<ClInclude Include="..\microscript\ILibAsyncSocket_Duktape.h" />
<ClInclude Include="..\microscript\ILibDuktapeModSearch.h" />
<ClInclude Include="..\microscript\ILibDuktape_ChildProcess.h" />
<ClInclude Include="..\microscript\ILibDuktape_Debugger.h" />
<ClInclude Include="..\microscript\ILibDuktape_Dgram.h" />
<ClInclude Include="..\microscript\ILibDuktape_DuplexStream.h" />

View File

@@ -187,6 +187,9 @@
<ClInclude Include="..\microscript\ILibDuktape_NetworkMonitor.h">
<Filter>Microscript</Filter>
</ClInclude>
<ClInclude Include="..\microscript\ILibDuktape_ChildProcess.h">
<Filter>Microscript</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\microscript\duktape.c">
@@ -337,6 +340,9 @@
<ClCompile Include="..\microscript\ILibDuktape_NetworkMonitor.c">
<Filter>Microscript</Filter>
</ClCompile>
<ClCompile Include="..\microscript\ILibDuktape_ChildProcess.c">
<Filter>Microscript</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="MeshConsole.rc" />

View File

@@ -29,6 +29,8 @@ limitations under the License.
#include <crtdbg.h>
#endif
#include "microscript/ILibDuktape_ScriptContainer.h"
MeshAgentHostContainer *agentHost = NULL;
#ifdef WIN32
@@ -64,45 +66,12 @@ void BreakSink(int s)
int main(int argc, char **argv)
{
// Check if .JS file is integrated with executable
FILE *tmpFile;
char *integratedJavaScript = NULL;
int integratedJavaScriptLen = 0;
#ifdef WIN32
if (ILibString_EndsWith(argv[0], -1, ".exe", 4) == 0)
{
sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "%s.exe", argv[0]);
tmpFile = fopen(ILibScratchPad, "rb");
}
else
{
tmpFile = fopen(argv[0], "rb");
}
#else
tmpFile = fopen(argv[0], "rb");
#endif
if (tmpFile != NULL)
{
fseek(tmpFile, 0, SEEK_END);
fseek(tmpFile, ftell(tmpFile) - 4, SEEK_SET);
ignore_result(fread(ILibScratchPad, 1, 4, tmpFile));
fseek(tmpFile, 0, SEEK_END);
if (ftell(tmpFile) == ntohl(((int*)ILibScratchPad)[0]))
{
fseek(tmpFile, ftell(tmpFile) - 8, SEEK_SET);
ignore_result(fread(ILibScratchPad, 1, 4, tmpFile));
integratedJavaScriptLen = ntohl(((int*)ILibScratchPad)[0]);
integratedJavaScript = ILibMemory_Allocate(1+integratedJavaScriptLen, 0, NULL, NULL);
fseek(tmpFile, 0, SEEK_END);
fseek(tmpFile, ftell(tmpFile) - 8 - integratedJavaScriptLen, SEEK_SET);
ignore_result(fread(integratedJavaScript, 1, integratedJavaScriptLen, tmpFile));
integratedJavaScript[integratedJavaScriptLen] = 0;
}
fclose(tmpFile);
}
int retCode = 0;
ILibDuktape_ScriptContainer_CheckEmbedded(argv, &integratedJavaScript, &integratedJavaScriptLen);
if (argc > 2 && memcmp(argv[1], "-faddr", 6) == 0)
{
uint64_t addrOffset;

View File

@@ -111,6 +111,11 @@ typedef struct ScriptContainerSettings
}ScriptContainerSettings;
#pragma pack(push, 1)
typedef struct MeshCommand_BinaryPacket_ServerId
{
unsigned short command;
char serverId[UTIL_HASHSIZE];
}MeshCommand_BinaryPacket_ServerId;
typedef struct MeshCommand_BinaryPacket_AuthRequest
{
unsigned short command;
@@ -1087,12 +1092,10 @@ int agent_GenerateCertificates(MeshAgentHostContainer *agent, char* certfile)
{
// Generate a new random node certificate
ILibRemoteLogging_printf(ILibChainGetLogger(agent->chain), ILibRemoteLogging_Modules_Agent_GuardPost, ILibRemoteLogging_Flags_VerbosityLevel_1, "...Generating new Node Certificate");
do
{
if (util_mkCert(NULL, &(agent->selfcert), 3072, 10000, "MeshNodeCertificate", CERTIFICATE_ROOT, NULL) == 0) return -1;
util_keyhash(agent->selfcert, agent->g_selfid);
} while (((int*)agent->g_selfid)[0] == 0); // This removes any chance that the self_id starts with 32 bits of zeros.
ILibRemoteLogging_printf(ILibChainGetLogger(agent->chain), ILibRemoteLogging_Modules_Agent_GuardPost, ILibRemoteLogging_Flags_VerbosityLevel_1, "...g_selfid = %s", ILibRemoteLogging_ConvertToHex(agent->g_selfid, (int)sizeof(agent->g_selfid)));
}
@@ -1361,7 +1364,6 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge
// Hash the server's web certificate and check if it matches the one in the auth request
util_keyhash2(peer, ILibScratchPad2); // Hash the server certificate public key and place it
if (memcmp(ILibScratchPad2, AuthRequest->serverHash, sizeof(AuthRequest->serverHash)) != 0) { printf("Bad server certificate hash\r\n"); break; } // TODO: Disconnect
memcpy_s(agent->serverNonce, sizeof(agent->serverNonce), AuthRequest->serverNonce, sizeof(AuthRequest->serverNonce));
@@ -1418,8 +1420,13 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge
if (!d2i_X509(&serverCert, (const unsigned char**)&AuthVerify->cert, AuthVerify->certLen)) { printf("Invalid server certificate\r\n"); break; } // TODO: Disconnect
// Check if this certificate public key hash matches what we want
X509_pubkey_digest(serverCert, EVP_sha384(), (unsigned char*)ILibScratchPad, (unsigned int*)&hashlen); // OpenSSL 1.1
if (memcmp(ILibScratchPad, agent->serverHash, UTIL_HASHSIZE) != 0) { printf("Server certificate mismatch\r\n"); break; } // TODO: Disconnect
X509_pubkey_digest(serverCert, EVP_sha384(), (unsigned char*)ILibScratchPad, (unsigned int*)&hashlen); // OpenSSL 1.1, SHA384
if (memcmp(ILibScratchPad, agent->serverHash, UTIL_HASHSIZE) != 0) {
X509_pubkey_digest(serverCert, EVP_sha256(), (unsigned char*)ILibScratchPad, (unsigned int*)&hashlen); // OpenSSL 1.1, SHA256 (For older .mshx policy file)
if (memcmp(ILibScratchPad, agent->serverHash, 32) != 0) {
printf("Server certificate mismatch\r\n"); break; // TODO: Disconnect
}
}
// Compute the authentication hash
SHA384_Init(&c);
@@ -1440,6 +1447,7 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge
// Send to the server information about this agent (TODO: Replace this with a struct)
MeshCommand_BinaryPacket_AuthInfo *info = (MeshCommand_BinaryPacket_AuthInfo*)ILibScratchPad2;
memset(info, 0, sizeof(MeshCommand_BinaryPacket_AuthInfo)); // Required because if hash are SHA256, they will not fully fill the struct.
info->command = htons(MeshCommand_AuthInfo);
info->infoVersion = htonl(1);
info->agentId = htonl(MESH_AGENTID);
@@ -1777,6 +1785,12 @@ void MeshServer_OnResponse(ILibWebClient_StateObject WebStateObject, int Interru
agent->serverAuthState = 0; // We are not authenticated. Bitmask: 1 = Server Auth, 2 = Agent Auth.
agent->serverConnectionState = 2;
// Send the ServerID to the server, this is useful for the server to use the correct certificate to authenticate.
MeshCommand_BinaryPacket_ServerId *serveridcmd = (MeshCommand_BinaryPacket_ServerId*)ILibScratchPad2;
serveridcmd->command = htons(MeshCommand_ServerId);
memcpy_s(serveridcmd->serverId, sizeof(serveridcmd->serverId), agent->serverHash, sizeof(agent->serverHash)); // Place our mesh agent nonce
ILibWebClient_WebSocket_Send(WebStateObject, ILibWebClient_WebSocket_DataType_BINARY, (char*)serveridcmd, sizeof(MeshCommand_BinaryPacket_ServerId), ILibAsyncSocket_MemoryOwnership_USER, ILibWebClient_WebSocket_FragmentFlag_Complete);
// Start authentication by sending a auth nonce & server TLS cert hash.
// Send 384 bits SHA384 hash of TLS cert public key + 384 bits nonce
util_random(sizeof(agent->agentNonce), agent->agentNonce); // Generate a new mesh agent connection nonce
@@ -1977,11 +1991,14 @@ void MeshServer_ConnectEx(MeshAgentHostContainer *agent)
return;
}
memset(agent->serverHash, 0, sizeof(agent->serverHash));
util_hexToBuf(f->data, f->datalength, agent->serverHash);
ILibDestructParserResults(rs);
if (ILibSimpleDataStore_Get(agent->masterDb, "MeshID", ILibScratchPad, sizeof(ILibScratchPad)) == 0) { printf("MeshID entry not found in Db!\n"); return; }
memcpy_s(agent->meshId, sizeof(agent->meshId), ILibScratchPad, UTIL_HASHSIZE);
len = ILibSimpleDataStore_Get(agent->masterDb, "MeshID", ILibScratchPad, sizeof(ILibScratchPad));
if ((len != 32) && (len != 48)) { printf("MeshID entry not found in db or bad size.\n"); return; } // Make sure MeshID is both present and SHA256 or SHA384.
memset(agent->meshId, 0, sizeof(agent->meshId)); // Clear the meshid first in case we copy SHA256
memcpy_s(agent->meshId, sizeof(agent->meshId), ILibScratchPad, len); // Copy the correct length
#ifndef MICROSTACK_NOTLS
util_keyhash(agent->selfcert, agent->g_selfid); // Compute our own identifier using our certificate
@@ -2393,6 +2410,7 @@ int MeshAgent_AgentMode(MeshAgentHostContainer *agentHost, int paramLen, char **
#endif
// Check to see if we need to import a settings file
importSettings(agentHost, MeshAgent_MakeAbsolutePath(agentHost->exePath, ".mshx"));
importSettings(agentHost, MeshAgent_MakeAbsolutePath(agentHost->exePath, ".msh"));
#ifdef WIN32

View File

@@ -92,6 +92,7 @@ typedef enum MeshCommands_Binary
MeshCommand_AuthVerify = 2, // Agent or server signature
MeshCommand_AuthInfo = 3, // Agent information
MeshCommand_AuthConfirm = 4, // Server confirm to the agent that is it authenticated
MeshCommand_ServerId = 5, // Optional, agent sends the expected serverid to the server. Useful if the server has many server certificates.
MeshCommand_CoreModule = 10, // New core modules to be used instead of the old one, if empty, remove the core module
MeshCommand_CoreModuleHash = 11, // Request/return the SHA384 hash of the core module
MeshCommand_AgentHash = 12, // Request/return the SHA384 hash of the agent executable

View File

@@ -259,6 +259,7 @@
<ClCompile Include="..\microscript\duktape.c" />
<ClCompile Include="..\microscript\ILibAsyncSocket_Duktape.c" />
<ClCompile Include="..\microscript\ILibDuktapeModSearch.c" />
<ClCompile Include="..\microscript\ILibDuktape_ChildProcess.c" />
<ClCompile Include="..\microscript\ILibDuktape_Debugger.c" />
<ClCompile Include="..\microscript\ILibDuktape_Dgram.c" />
<ClCompile Include="..\microscript\ILibDuktape_DuplexStream.c" />
@@ -321,6 +322,7 @@
<ClInclude Include="..\microscript\duk_config.h" />
<ClInclude Include="..\microscript\ILibAsyncSocket_Duktape.h" />
<ClInclude Include="..\microscript\ILibDuktapeModSearch.h" />
<ClInclude Include="..\microscript\ILibDuktape_ChildProcess.h" />
<ClInclude Include="..\microscript\ILibDuktape_Debugger.h" />
<ClInclude Include="..\microscript\ILibDuktape_Dgram.h" />
<ClInclude Include="..\microscript\ILibDuktape_DuplexStream.h" />

View File

@@ -184,6 +184,9 @@
<ClCompile Include="..\microstack\ILibIPAddressMonitor.c">
<Filter>Microstack</Filter>
</ClCompile>
<ClCompile Include="..\microscript\ILibDuktape_ChildProcess.c">
<Filter>Microscript</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\microscript\duk_config.h">
@@ -358,5 +361,8 @@
<ClInclude Include="..\microstack\ILibIPAddressMonitor.h">
<Filter>Microstack</Filter>
</ClInclude>
<ClInclude Include="..\microscript\ILibDuktape_ChildProcess.h">
<Filter>Microscript</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@@ -35,6 +35,8 @@ limitations under the License.
#include "microstack/ILibCrypto.h"
#include "meshcore/agentcore.h"
#include "microscript/ILibDuktape_ScriptContainer.h"
#ifndef _MINCORE
// #include "../kvm/kvm.h"
int SetupWindowsFirewall(wchar_t* processname);
@@ -702,6 +704,10 @@ int main(int argc, char* argv[])
return(0);
}
char *integratedJavaScript;
int integragedJavaScriptLen;
ILibDuktape_ScriptContainer_CheckEmbedded(argv, &integratedJavaScript, &integragedJavaScriptLen);
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
// Process extra switches
@@ -759,7 +765,7 @@ int main(int argc, char* argv[])
return 0;
}
#else
else if (argc > 1 && ((strcasecmp(argv[1], "run") == 0) || (strcasecmp(argv[1], "--slave") == 0)))
else if (integratedJavaScript != NULL || (argc > 1 && ((strcasecmp(argv[1], "run") == 0) || (strcasecmp(argv[1], "--slave") == 0))))
{
// Run the mesh agent in console mode, since the agent is compiled for windows service, the KVM will not work right. This is only good for testing.
SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE); // Set SIGNAL on windows to listen for Ctrl-C
@@ -767,6 +773,8 @@ int main(int argc, char* argv[])
__try
{
agent = MeshAgent_Create();
agent->meshCoreCtx_embeddedScript = integratedJavaScript;
agent->meshCoreCtx_embeddedScriptLen = integragedJavaScriptLen;
MeshAgent_Start(agent, argc, argv);
retCode = agent->exitCode;
MeshAgent_Destroy(agent);

View File

@@ -136,7 +136,7 @@ void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
// Run the MicroLMS Service
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
Chain = ILibCreateChain();
MicroLMS = ILibLMS_Create(Chain, selfexe);
MicroLMS = ILibLMS_Create(Chain, selfexe, NULL);
if (MicroLMS != NULL)
{
printf("Starting MicroLMS.\r\n");
@@ -580,7 +580,7 @@ int main(int argc, char* argv[])
{
// Run as an command line application
Chain = ILibCreateChain();
MicroLMS = ILibLMS_Create(Chain, selfexe);
MicroLMS = ILibLMS_Create(Chain, selfexe, NULL);
if (MicroLMS != NULL)
{
#ifdef NOCOMMANDER

View File

@@ -0,0 +1,285 @@
#include "ILibDuktape_ChildProcess.h"
#include "ILibDuktapeModSearch.h"
#include "../microstack/ILibParsers.h"
#include "../microstack/ILibProcessPipe.h"
#include "ILibDuktape_Helpers.h"
#include "ILibDuktape_ReadableStream.h"
#include "ILibDuktape_WritableStream.h"
#include "ILibDuktape_EventEmitter.h"
#define ILibDuktape_ChildProcess_Manager "\xFF_ChildProcess_Manager"
#define ILibDuktape_ChildProcess_Process "\xFF_ChildProcess_Process"
#define ILibDuktape_ChildProcess_MemBuf "\xFF_ChildProcess_MemBuf"
typedef struct ILibDuktape_ChildProcess_SubProcess
{
duk_context *ctx;
void *subProcess;
void *chain;
ILibProcessPipe_Process childProcess;
ILibDuktape_readableStream *stdOut;
ILibDuktape_readableStream *stdErr;
ILibDuktape_WritableStream *stdIn;
int exitCode;
}ILibDuktape_ChildProcess_SubProcess;
void ILibDuktape_ChildProcess_SubProcess_StdOut_OnPause(ILibDuktape_readableStream *sender, void *user)
{
ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)user;
ILibProcessPipe_Pipe_Pause(ILibProcessPipe_Process_GetStdOut(p->childProcess));
}
void ILibDuktape_ChildProcess_SubProcess_StdOut_OnResume(ILibDuktape_readableStream *sender, void *user)
{
ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)user;
ILibProcessPipe_Pipe_Resume(ILibProcessPipe_Process_GetStdOut(p->childProcess));
}
void ILibDuktape_ChildProcess_SubProcess_StdErr_OnPause(ILibDuktape_readableStream *sender, void *user)
{
ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)user;
ILibProcessPipe_Pipe_Pause(ILibProcessPipe_Process_GetStdErr(p->childProcess));
}
void ILibDuktape_ChildProcess_SubProcess_StdErr_OnResume(ILibDuktape_readableStream *sender, void *user)
{
ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)user;
ILibProcessPipe_Pipe_Resume(ILibProcessPipe_Process_GetStdErr(p->childProcess));
}
ILibTransport_DoneState ILibDuktape_ChildProcess_SubProcess_StdIn_WriteHandler(ILibDuktape_WritableStream *stream, char *buffer, int bufferLen, void *user)
{
ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)user;
return(ILibProcessPipe_Process_WriteStdIn(p->childProcess, buffer, bufferLen, ILibTransport_MemoryOwnership_USER));
}
void ILibDuktape_ChildProcess_SubProcess_StdIn_EndHandler(ILibDuktape_WritableStream *sender, void *user)
{
}
void ILibDuktape_ChildProcess_SubProcess_ExitHandler(ILibProcessPipe_Process sender, int exitCode, void* user)
{
ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)user;
p->exitCode = exitCode;
duk_push_heapptr(p->ctx, p->subProcess); // [childProcess]
duk_get_prop_string(p->ctx, -1, "emit"); // [childProcess][emit]
duk_swap_top(p->ctx, -2); // [emit][this]
duk_push_string(p->ctx, "exit"); // [emit][this][exit]
duk_push_int(p->ctx, p->exitCode); // [emit][this][exit][exitCode]
duk_push_null(p->ctx); // [emit][this][exit][exitCode][sig]
if (duk_pcall_method(p->ctx, 3) != 0) { ILibDuktape_Process_UncaughtExceptionEx(p->ctx, "child_process.subProcess.exit(): "); }
duk_pop(p->ctx);
}
void ILibDuktape_ChildProcess_SubProcess_StdOutHandler(ILibProcessPipe_Process sender, char *buffer, int bufferLen, int* bytesConsumed, void* user)
{
ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)user;
ILibDuktape_readableStream_WriteData(p->stdOut, buffer, bufferLen);
*bytesConsumed = bufferLen;
}
void ILibDuktape_ChildProcess_SubProcess_StdErrHandler(ILibProcessPipe_Process sender, char *buffer, int bufferLen, int* bytesConsumed, void* user)
{
ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)user;
ILibDuktape_readableStream_WriteData(p->stdErr, buffer, bufferLen);
*bytesConsumed = bufferLen;
}
void ILibDuktape_ChildProcess_SubProcess_SendOK(ILibProcessPipe_Process sender, void* user)
{
ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)user;
ILibDuktape_WritableStream_Ready(p->stdIn);
}
duk_ret_t ILibDuktape_ChildProcess_Kill(duk_context *ctx)
{
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, ILibDuktape_ChildProcess_MemBuf);
ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)Duktape_GetBuffer(ctx, -1, NULL);
ILibProcessPipe_Process_SoftKill(p->childProcess);
return(0);
}
ILibDuktape_ChildProcess_SubProcess* ILibDuktape_ChildProcess_SpawnedProcess_PUSH(duk_context *ctx, ILibProcessPipe_Process mProcess, void *callback)
{
duk_push_object(ctx); // [ChildProcess]
duk_push_pointer(ctx, mProcess); // [ChildProcess][ptr]
duk_put_prop_string(ctx, -2, ILibDuktape_ChildProcess_Process); // [ChildProcess]
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_ChildProcess_SubProcess)); // [ChildProcess][buffer]
ILibDuktape_ChildProcess_SubProcess *retVal = (ILibDuktape_ChildProcess_SubProcess*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, ILibDuktape_ChildProcess_MemBuf); // [ChildProcess]
memset(retVal, 0, sizeof(ILibDuktape_ChildProcess_SubProcess));
retVal->ctx = ctx;
retVal->subProcess = duk_get_heapptr(ctx, -1);
retVal->childProcess = mProcess;
retVal->chain = Duktape_GetChain(ctx);
ILibDuktape_CreateReadonlyProperty_int(ctx, "pid", ILibProcessPipe_Process_GetPID(mProcess));
ILibDuktape_EventEmitter *emitter = ILibDuktape_EventEmitter_Create(ctx);
ILibDuktape_EventEmitter_CreateEventEx(emitter, "exit");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "error");
ILibDuktape_CreateInstanceMethod(ctx, "kill", ILibDuktape_ChildProcess_Kill, 0);
duk_push_object(ctx);
retVal->stdOut = ILibDuktape_ReadableStream_Init(ctx, ILibDuktape_ChildProcess_SubProcess_StdOut_OnPause, ILibDuktape_ChildProcess_SubProcess_StdOut_OnResume, retVal);
ILibDuktape_CreateReadonlyProperty(ctx, "stdout");
duk_push_object(ctx);
retVal->stdErr = ILibDuktape_ReadableStream_Init(ctx, ILibDuktape_ChildProcess_SubProcess_StdErr_OnPause, ILibDuktape_ChildProcess_SubProcess_StdErr_OnResume, retVal);
ILibDuktape_CreateReadonlyProperty(ctx, "stderr");
duk_push_object(ctx);
retVal->stdIn = ILibDuktape_WritableStream_Init(ctx, ILibDuktape_ChildProcess_SubProcess_StdIn_WriteHandler, ILibDuktape_ChildProcess_SubProcess_StdIn_EndHandler, retVal);
ILibDuktape_CreateReadonlyProperty(ctx, "stdin");
if (callback != NULL) { ILibDuktape_EventEmitter_AddOnce(emitter, "exit", callback); }
ILibProcessPipe_Process_AddHandlers(mProcess, 4096, ILibDuktape_ChildProcess_SubProcess_ExitHandler,
ILibDuktape_ChildProcess_SubProcess_StdOutHandler,
ILibDuktape_ChildProcess_SubProcess_StdErrHandler,
ILibDuktape_ChildProcess_SubProcess_SendOK, retVal);
return(retVal);
}
duk_ret_t ILibDuktape_ChildProcess_Manager_Finalizer(duk_context *ctx)
{
duk_get_prop_string(ctx, 0, ILibDuktape_ChildProcess_Manager);
ILibProcessPipe_Manager manager = (ILibProcessPipe_Manager)duk_get_pointer(ctx, -1);
ILibChain_SafeRemove(((ILibChain_Link*)manager)->ParentChain, manager);
return(0);
}
duk_ret_t ILibDuktape_ChildProcess_execFile(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, ILibDuktape_ChildProcess_Manager);
ILibProcessPipe_Manager manager = (ILibProcessPipe_Manager)duk_get_pointer(ctx, -1);
duk_size_t targetLen;
char *target = (char*)duk_get_lstring(ctx, 0, &targetLen);
char **args = NULL;
int i, x;
void *callback = NULL;
ILibProcessPipe_Process p = NULL;
for (i = 0; i < nargs; ++i)
{
if (duk_is_array(ctx, i) != 0)
{
int arrLen = duk_get_length(ctx, i);
#ifdef WIN32
args = (char**)_alloca((arrLen + 1) * sizeof(char*));
#else
args = (char**)alloca((arrLen + 1) * sizeof(char*));
#endif
for (x = 0; x < arrLen; ++x)
{
duk_get_prop_index(ctx, i, x);
args[x] = (char*)duk_get_string(ctx, -1);
}
args[x] = NULL;
}
else if (duk_is_function(ctx, i))
{
callback = duk_get_heapptr(ctx, i);
}
}
#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
p = ILibProcessPipe_Manager_SpawnProcess(manager, target, args);
if (p == NULL)
{
return(ILibDuktape_Error(ctx, "child_process.execFile(): Could not exec [%s]", target));
}
ILibDuktape_ChildProcess_SpawnedProcess_PUSH(ctx, p, callback);
return(1);
}
void ILibDuktape_ChildProcess_PUSH(duk_context *ctx, void *chain)
{
duk_push_object(ctx);
duk_push_pointer(ctx, (void*)ILibProcessPipe_Manager_Create(chain));
duk_put_prop_string(ctx, -2, ILibDuktape_ChildProcess_Manager);
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_ChildProcess_Manager_Finalizer);
ILibDuktape_CreateInstanceMethod(ctx, "execFile", ILibDuktape_ChildProcess_execFile, DUK_VARARGS);
}
void ILibDuktape_ChildProcess_Init(duk_context *ctx)
{
ILibDuktape_ModSearch_AddHandler(ctx, "child_process", ILibDuktape_ChildProcess_PUSH);
}
#ifdef __DOXY__
/*!
\implements EventEmitter
\brief The child_process module provides the ability to spawn child processes. <b>Note:</b> To use, must <b>require('child_process')</b>
*/
class ChildProcess
{
public:
/*!
\brief The specified file is spawned as a child process
\param file \<String\> Required. The name or path of the executable file to run
\param args \<String[]\> Optional. List of string arguments
\param options <Object> Optional. \n
cwd \<String\> Current working directory\n
env <Object> Environment key-value pairs\n
timeout <number> <b>Default</b>: 0\n
\returns \<ChildProcess\>
*/
static ChildProcess execFile(file[, args][, options][, callback]);
/*!
\brief Event emitted whenever process cannot be killed or spawned
\param err <Error> The Error
*/
void error;
/*!
\brief Event emitted after the child process ends
\param code <number> Exit code
\param signal \<String\> Not used.
*/
void exit;
/*!
\brief Process ID of the child process
*/
Integer pid;
/*!
\brief Sends SIGTERM to child process
*/
void kill();
/*!
\brief StdOut ReadableStream
*/
ReadableStream stdout;
/*!
\brief StdErr ReadableStream
*/
ReadableStream stderr;
/*!
\brief StdIn WritableStream
*/
WritableStream stdin;
};
#endif

View File

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

View File

@@ -30,8 +30,11 @@ void ILibDuktape_EventEmitter_RemoveEventHeapptr(ILibDuktape_EventEmitter *emitt
int ILibDuktape_EventEmitter_AddEventHeapptr(ILibDuktape_EventEmitter *emitter, char *eventName, void **heapptr); // Add Callback after the fact
int ILibDuktape_EventEmitter_AddSink(ILibDuktape_EventEmitter *emitter, char *eventName, ILibDuktape_EventEmitter_Handler handler); // Add Native Event Handler
int ILibDuktape_EventEmitter_AddOnce(ILibDuktape_EventEmitter *emitter, char *eventName, void *heapptr); // Add native event handler 'once'
int ILibDuktape_EventEmitter_AddOnceEx(ILibDuktape_EventEmitter *emitter, char *eventName, duk_c_function func, duk_idx_t funcArgs);
int ILibDuktape_EventEmitter_AddOnceEx2(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func, duk_idx_t funcArgs);
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);

View File

@@ -37,7 +37,21 @@ struct sockaddr_in6 duktape_internalAddress;
#define ILibDuktape_EventEmitter_Table "\xFF_EventEmitterTable"
#define ILibDuktape_Process_ExitCode "\xFF_ExitCode"
#define ILibDuktape_Memory_AllocTable "\xFF_MemoryAllocTable"
#define ILibDuktape_ObjectStashKey "\xFF_ObjectStashKey"
void ILibDuktape_Push_ObjectStash(duk_context *ctx)
{
if (duk_has_prop_string(ctx, -1, ILibDuktape_ObjectStashKey))
{
duk_get_prop_string(ctx, -1, ILibDuktape_ObjectStashKey); // [obj][stash]
}
else
{
duk_push_object(ctx); // [obj][stash]
duk_dup(ctx, -1); // [obj][stash][stash]
duk_put_prop_string(ctx, -3, ILibDuktape_ObjectStashKey); // [obj][stash]
}
}
duk_ret_t ILibDuktape_Error(duk_context *ctx, char *format, ...)
{
char dest[4096];
@@ -444,25 +458,13 @@ void ILibDuktape_Process_UncaughtException(duk_context *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))
if (duk_has_prop_string(ctx, -1, "\xFF_ScriptContainerSettings_DB"))
{
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_get_prop_string(ctx, -1, "\xFF_ScriptContainerSettings_DB"); // [stash][db]
if (duk_get_pointer(ctx, -1) != NULL) { retVal = "0"; }
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;

View File

@@ -83,4 +83,6 @@ void ILibDuktape_CreateReadonlyProperty(duk_context *ctx, char *propName);
void *ILibDuktape_Memory_Alloc(duk_context *ctx, duk_size_t size);
void ILibDuktape_Helper_AddHeapFinalizer(duk_context *ctx, ILibDuktape_HelperEvent handler, void *user);
void ILibDuktape_Push_ObjectStash(duk_context *ctx);
#endif

View File

@@ -81,7 +81,17 @@ duk_ret_t ILibDuktape_Polyfills_Buffer_from(duk_context *ctx)
char *buffer;
int bufferLen;
if (!(nargs == 2 && duk_is_string(ctx, 0) && duk_is_string(ctx, 1)))
if (nargs == 1)
{
str = (char*)duk_get_lstring(ctx, 0, &strlength);
duk_push_fixed_buffer(ctx, strlength + 1);
buffer = Duktape_GetBuffer(ctx, -1, NULL);
memcpy_s(buffer, strlength + 1, str, strlength);
buffer[strlength] = 0;
duk_push_buffer_object(ctx, -1, 0, strlength+1, DUK_BUFOBJ_ARRAYBUFFER);
return(1);
}
else 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);
@@ -97,14 +107,14 @@ duk_ret_t ILibDuktape_Polyfills_Buffer_from(duk_context *ctx)
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);
duk_push_buffer_object(ctx, -1, 0, bufferLen, DUK_BUFOBJ_ARRAYBUFFER);
}
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);
duk_push_buffer_object(ctx, -1, 0, bufferLen, DUK_BUFOBJ_ARRAYBUFFER);
}
else
{
@@ -219,9 +229,27 @@ duk_ret_t ILibDuktape_Polyfills_Console_log(duk_context *ctx)
else
{
duk_dup(ctx, i);
if (strcmp("[object Object]", duk_to_string(ctx, -1)) == 0)
{
duk_pop(ctx);
duk_dup(ctx, i);
printf("%s", (i == 0 ? "{" : ", {"));
duk_enum(ctx, -1, DUK_ENUM_OWN_PROPERTIES_ONLY);
int propNum = 0;
while (duk_next(ctx, -1, 1))
{
printf("%s%s: %s", ((propNum++ == 0) ? " " : ", "), (char*)duk_to_string(ctx, -2), (char*)duk_to_string(ctx, -1));
duk_pop_2(ctx);
}
duk_pop(ctx);
printf(" }");
}
else
{
printf("%s%s", (i == 0 ? "" : ", "), duk_to_string(ctx, -1));
}
}
}
printf("\n");
return 0;
}

View File

@@ -386,10 +386,13 @@ int ILibDuktape_readableStream_WriteDataEx(ILibDuktape_readableStream *stream, i
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); }
sem_wait(&(stream->pipeLock));
stream->extBuffer_Reserved = streamReserved;
stream->extBuffer_buffer = buffer;
stream->extBuffer_bufferLen = bufferLen;
sem_post(&(stream->pipeLock));
if (stream->paused == 0 && stream->PauseHandler != NULL) { stream->paused = 1; stream->PauseHandler(stream, stream->user); }
ILibChain_RunOnMicrostackThread(stream->chain, ILibDuktape_readableStream_WriteData_OnData_ChainThread, stream);
}
}

View File

@@ -57,7 +57,11 @@ limitations under the License.
#include "ILibDuktape_SHA256.h"
#include "ILibDuktape_EncryptionStream.h"
#include "ILibDuktape_ChildProcess.h"
#ifdef _POSIX
extern char **environ;
#endif
#define SCRIPT_ENGINE_PIPE_BUFFER_SIZE 65535
#define ILibDuktape_ScriptContainer_MasterPtr "\xFF_ScriptContainer_MasterPtr"
#define ILibDuktape_ScriptContainer_SlavePtr "\xFF_ScriptContainer_SlavePtr"
@@ -183,6 +187,58 @@ void ILibDuktape_ScriptContainer_Slave_OnBrokenPipe(ILibProcessPipe_Pipe sender)
ILibStopChain(((ILibDuktape_ScriptContainer_Slave*)((void**)ILibMemory_GetExtraMemory(sender, ILibMemory_ILibProcessPipe_Pipe_CONTAINERSIZE))[0])->chain);
}
void ILibDuktape_ScriptContainer_CheckEmbedded(char **argv, char **script, int *scriptLen)
{
// Check if .JS file is integrated with executable
FILE *tmpFile;
char *integratedJavaScript = NULL;
int integratedJavaScriptLen = 0;
#ifdef WIN32
if (ILibString_EndsWith(argv[0], -1, ".exe", 4) == 0)
{
sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "%s.exe", argv[0]);
tmpFile = fopen(ILibScratchPad, "rb");
}
else
{
tmpFile = fopen(argv[0], "rb");
}
#else
tmpFile = fopen(argv[0], "rb");
#endif
if (tmpFile != NULL)
{
fseek(tmpFile, 0, SEEK_END);
fseek(tmpFile, ftell(tmpFile) - 4, SEEK_SET);
ignore_result(fread(ILibScratchPad, 1, 4, tmpFile));
fseek(tmpFile, 0, SEEK_END);
if (ftell(tmpFile) == ntohl(((int*)ILibScratchPad)[0]))
{
fseek(tmpFile, ftell(tmpFile) - 8, SEEK_SET);
ignore_result(fread(ILibScratchPad, 1, 4, tmpFile));
integratedJavaScriptLen = ntohl(((int*)ILibScratchPad)[0]);
integratedJavaScript = ILibMemory_Allocate(1 + integratedJavaScriptLen, 0, NULL, NULL);
fseek(tmpFile, 0, SEEK_END);
fseek(tmpFile, ftell(tmpFile) - 8 - integratedJavaScriptLen, SEEK_SET);
ignore_result(fread(integratedJavaScript, 1, integratedJavaScriptLen, tmpFile));
integratedJavaScript[integratedJavaScriptLen] = 0;
}
fclose(tmpFile);
}
*script = integratedJavaScript;
*scriptLen = integratedJavaScriptLen;
}
// Polyfill process object:
void ILibDuktape_ScriptContainer_Process_ExitCallback(void *obj)
{
@@ -247,6 +303,49 @@ duk_ret_t ILibDuktape_ScriptContainer_Process_Argv(duk_context *ctx)
return 1;
}
duk_ret_t ILibDuktape_ScriptContainer_Process_env(duk_context *ctx)
{
duk_push_object(ctx); // [env]
#ifdef WIN32
int i;
char *envStrings = GetEnvironmentStringsA();
int envStringsLen = ILibString_IndexOf(envStrings, INT_MAX, "\0\0", 2);
if (envStringsLen > 0)
{
parser_result *r = ILibParseString(envStrings, 0, envStringsLen, "\0", 1);
parser_result_field *f = r->FirstResult;
while (f != NULL)
{
i = ILibString_IndexOf(f->data, f->datalength, "=", 1);
if (i > 0)
{ // [env]
duk_push_lstring(ctx, f->data, i); // [env][key]
duk_push_string(ctx, f->data + i + 1); // [env][key][val]
duk_put_prop(ctx, -3); // [env]
}
f = f->NextResult;
}
ILibDestructParserResults(r);
}
FreeEnvironmentStringsA(envStrings);
#elif defined(_POSIX)
for (char **env = environ; *env; ++env)
{
int envLen = (int)strnlen_s(*env, INT_MAX);
int i = ILibString_IndexOf(*env, envLen, "=", 1);
if (i > 0)
{
duk_push_lstring(ctx, *env, i);
duk_push_string(ctx, *env + i + 1);
duk_put_prop(ctx, -3);
}
}
#endif
return(1);
}
void ILibDuktape_ScriptContainer_Process_Init(duk_context *ctx, char **argList)
{
int i = 0;
@@ -254,6 +353,8 @@ void ILibDuktape_ScriptContainer_Process_Init(duk_context *ctx, char **argList)
duk_push_global_object(ctx); // [g]
duk_push_object(ctx); // [g][process]
ILibDuktape_CreateEventWithGetter(ctx, "env", ILibDuktape_ScriptContainer_Process_env);
#if defined(WIN32) // [g][process][platform]
duk_push_string(ctx, "win32");
#elif defined(__APPLE__)
@@ -263,6 +364,19 @@ void ILibDuktape_ScriptContainer_Process_Init(duk_context *ctx, char **argList)
#endif
duk_put_prop_string(ctx, -2, "platform"); // [g][process]
duk_push_heap_stash(ctx); // [g][process][stash]
if (duk_has_prop_string(ctx, -1, ILibDuktape_ScriptContainer_ExePath))
{
duk_get_prop_string(ctx, -1, ILibDuktape_ScriptContainer_ExePath); // [g][process][stash][path]
duk_swap_top(ctx, -2); // [g][process][path][stash]
duk_pop(ctx); // [g][process][path]
ILibDuktape_CreateReadonlyProperty(ctx, "execPath"); // [g][process]
}
else
{
duk_pop(ctx); // [g][process]
}
if (argList != NULL)
{
duk_push_array(ctx); // [g][process][array]
@@ -691,7 +805,7 @@ duk_context *ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx(SCRIPT_ENG
ILibDuktape_DGram_Init(ctx); // Datagram Sockets
}
if ((securityFlags & SCRIPT_ENGINE_NO_GENERIC_MARSHAL_ACCESS) == 0) { ILibDuktape_GenericMarshal_init(ctx); }
if ((securityFlags & SCRIPT_ENGINE_NO_PROCESS_SPAWNING) == 0) { ILibDuktape_ProcessPipe_Init(ctx, chain); }
if ((securityFlags & SCRIPT_ENGINE_NO_PROCESS_SPAWNING) == 0) { ILibDuktape_ProcessPipe_Init(ctx, chain); ILibDuktape_ChildProcess_Init(ctx); }
if ((securityFlags & SCRIPT_ENGINE_NO_FILE_SYSTEM_ACCESS) == 0) { ILibDuktape_fs_init(ctx); }

View File

@@ -140,6 +140,7 @@ typedef struct SCRIPT_ENGINE_SETTINGS
}SCRIPT_ENGINE_SETTINGS;
void ILibDuktape_ScriptContainer_CheckEmbedded(char **argv, char **script, int *scriptLen);
void ILibDuktape_ScriptContainer_InitMaster(void *chain, char *exePath, ILibProcessPipe_Manager manager);
int ILibDuktape_ScriptContainer_StartSlave(void *chain, ILibProcessPipe_Manager manager);

View File

@@ -35,6 +35,7 @@ limitations under the License.
#include "ILibDuktape_DuplexStream.h"
#include "ILibDuktape_EventEmitter.h"
#include "microstack/ILibCrypto.h"
#include "microstack/ILibRemoteLogging.h"
#define HTTP_SERVER_PTR "\xFF_ServerPtr"
#define HTTP_WEBCLIENT_MGR "_RequestManagerPtr"
@@ -52,13 +53,20 @@ limitations under the License.
#define HTTP_STREAM_WRAPPER_BUFSIZE 4096
#define HTTP_CLIENTREQUEST_PARAMETER "\xFF_http_clientRequest_parameter"
#define CLIENTREQUEST_HTTP "\xFF_clientRequest_HTTP"
#define CLIENTREQUEST_SOCKET_WCDO "\xFF_clientRequest_SOCKET_WCDO"
#define HTTP_INCOMINGMSG_WebStateObject "\xFF_incomingMessage_WebStateObject"
#define DIGEST_USERNAME "\xFF_DigestUsername"
#define DIGEST_PASSWORD "\xFF_DigestPassword"
#define DIGEST_WCDO "\xFF_DIGEST_WCDO"
#define HTTP_DIGEST "\xFF_HTTP_DIGEST"
#define DIGEST_CLIENT_REQUEST "\xFF_DIGEST_CLIENT_REQUEST"
#define HTTP_CLIENTREQUEST_DATAPTR "\xFF_CLIENTREQUEST_DATAPTR"
#define CLIENTREQUEST_EVENT_NAME "\xFF_CLIENTREQUEST_EVENT_NAME"
#define CLIENTREQUEST_IMSG_RSPTR "\xFF_CLIENTREQUEST_IMSG_RSPTR"
#define DIGESTCLIENTREQUEST_END_CALLED "\xFF_DIGESTCLIENTREQUEST_END_CALLED"
#define DIGESTCLIENTREQUEST_CONTINUE "\xFF_DIGESTCLIENTREQUEST_CONTINUE"
#define DIGESTCLIENTREQUEST_TmpBuffer "\xFF_DIGESTCLIENTREQUEST_TmpBuffer"
#define DIGESTCLIENTREQUEST_DIGEST "\xFF_DIGESTCLIENTREQUEST_DIGEST"
extern duk_idx_t ILibWebServer_DukTape_Push_ILibWebServerSession(duk_context *ctx, ILibWebServer_Session *session);
void* ILibDuktape_http_request_PUSH_clientRequest(duk_context *ctx, ILibWebClient_RequestToken token, int isWebSocket);
@@ -84,6 +92,7 @@ typedef struct ILibDuktape_http_requestClient_callbacks
void *requestStream;
void *OnReceive;
void *OnContinue;
void *OnSocket;
#ifndef MICROSTACK_NOTLS
int rejectUnauthorized;
void *checkServerIdentity;
@@ -954,6 +963,33 @@ duk_ret_t ILibDuktape_http_server_tlsSettings_Finalizer(duk_context *ctx)
{
return 0;
}
duk_ret_t ILibDuktape_http_server_address(duk_context *ctx)
{
duk_push_this(ctx);
if (!duk_has_prop_string(ctx, -1, HTTP_SERVER_PTR))
{
return(ILibDuktape_Error(ctx, "http.server.address(): Not listening"));
}
duk_get_prop_string(ctx, -1, HTTP_SERVER_PTR);
ILibAsyncServerSocket_ServerModule s = ILibWebServer_GetServerSocketModule((ILibWebServer_ServerToken)duk_get_pointer(ctx, -1));
struct sockaddr_in6 local;
memset(&local, 0, sizeof(struct sockaddr_in6));
ILibAsyncServerSocket_GetLocal(s, (struct sockaddr*)&local, sizeof(struct sockaddr_in6));
if (local.sin6_family == AF_UNSPEC) { return(ILibDuktape_Error(ctx, "net.server.address(): call to getsockname() failed")); }
duk_push_object(ctx);
duk_push_string(ctx, local.sin6_family == AF_INET6 ? "IPv6" : "IPv4");
duk_put_prop_string(ctx, -2, "family");
duk_push_int(ctx, (int)ntohs(local.sin6_port));
duk_put_prop_string(ctx, -2, "port");
duk_push_string(ctx, ILibRemoteLogging_ConvertAddress((struct sockaddr*)&local));
duk_put_prop_string(ctx, -2, "address");
return(1);
}
duk_ret_t ILibDuktape_http_createServer(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
@@ -1060,6 +1096,7 @@ duk_ret_t ILibDuktape_http_createServer(duk_context *ctx)
duk_push_c_function(ctx, ILibDuktape_http_server_listen, DUK_VARARGS); // [http][server][func]
duk_put_prop_string(ctx, -2, "listen"); // [http][server]
ILibDuktape_CreateInstanceMethod(ctx, "_address", ILibDuktape_http_server_address, 0);
return 1;
}
@@ -1096,14 +1133,12 @@ void ILibDuktape_http_request_OnResponse(ILibWebClient_StateObject WebStateObjec
{
if (ctx != NULL)
{
duk_push_heapptr(ctx, ptrs->OnReceive); // [func]
duk_push_heapptr(ctx, ptrs->clientRequest); // [func][this]
duk_del_prop_string(ctx, -1, HTTP_REQUEST_TOKEN_PTR); // (Prevents crash in Request Finalizer)
duk_push_null(ctx); // [func][this][null]
if (duk_pcall_method(ctx, 1) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(ctx);
}
duk_push_heapptr(ctx, ptrs->clientRequest); // [clientRequest]
duk_get_prop_string(ctx, -1, "emit"); // [clientRequest][emit]
duk_swap_top(ctx, -2); // [emit][this]
duk_push_string(ctx, "error"); // [emit][this][error]
duk_push_error_object(ctx, DUK_ERR_ERROR, "Socket was unexpectedly closed"); // [emit][this][error][err]
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "http.request.OnError(): "); }
duk_pop(ctx); // ...
}
return;
@@ -1147,6 +1182,7 @@ void ILibDuktape_http_request_OnResponse(ILibWebClient_StateObject WebStateObjec
{
duk_push_heapptr(ctx, ptrs->clientRequest); // [clientRequest]
duk_del_prop_string(ctx, -1, HTTP_REQUEST_TOKEN_PTR);
duk_del_prop_string(ctx, -1, HTTP_REQUEST_USER_PTR);
ILibDuktape_EventEmitter_RemoveAll(ILibDuktape_EventEmitter_GetEmitter(ctx, -1));
duk_pop(ctx); // ...
}
@@ -1479,8 +1515,27 @@ void ILibDuktape_http_webSocket_onSendOk(ILibWebClient_StateObject sender, void
ILibDuktape_DuplexStream_Ready(ptrs->stream);
}
}
void ILibDuktape_http_request_idleTimeout(ILibAsyncSocket_SocketModule sender, void *user)
{
ILibWebClient_RequestToken token = ILibWebClient_GetRequestToken_FromStateObject(user);
void ** u = ILibWebClient_RequestToken_GetUserObjects(token);
if (u[1] != NULL && ((ILibDuktape_http_request_dataType*)u[1])->STRUCT_TYPE == ILibDuktape_http_request_dataType_request &&
((ILibDuktape_http_requestClient_callbacks*)u[1])->clientRequest != NULL)
{
duk_context *ctx = (duk_context*)u[0];
ILibDuktape_http_requestClient_callbacks *cb = (ILibDuktape_http_requestClient_callbacks*)u[1];
duk_push_heapptr(ctx, cb->clientRequest); // [clientRequest]
duk_get_prop_string(ctx, -1, "emit"); // [clientRequest][emit]
duk_swap_top(ctx, -2); // [emit][this]
duk_push_string(ctx, "timeout"); // [emit][this][timeout]
if (duk_pcall_method(ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "http.clientRequest.onTimeout(): "); }
duk_pop(ctx);
}
}
duk_ret_t ILibDuktape_http_request(duk_context *ctx)
{
union { int i; void*p; }u;
ILibHTTPPacket *packet;
char *host;
duk_size_t hostLen;
@@ -1509,6 +1564,10 @@ duk_ret_t ILibDuktape_http_request(duk_context *ctx)
{
duk_get_prop_string(ctx, -1, HTTP_WEBCLIENT_MGR);
wcm = (ILibWebClient_RequestManager)duk_to_pointer(ctx, -1);
if (protocol == ILibWebClient_RequestToken_USE_HTTPS)
{
ILibWebClient_EnableHTTPS(wcm, NULL, NULL, ILibDuktape_http_request_tls_verify);
}
}
else
{
@@ -1589,7 +1648,6 @@ duk_ret_t ILibDuktape_http_request(duk_context *ctx)
if (isWebSocket != 0)
{
union { int i; void*p; }u;
int len;
char value[32];
char nonce[16];
@@ -1607,6 +1665,13 @@ duk_ret_t ILibDuktape_http_request(duk_context *ctx)
ILibHTTPPacket_Stash_Put(packet, "_WebSocketOnSendOK", -1, ILibDuktape_http_webSocket_onSendOk);
}
u.i = Duktape_GetIntPropertyValue(ctx, 0, "timeout", 0);
if (u.i > 0)
{
ILibHTTPPacket_Stash_Put(packet, "_idleTimeout", -1, u.p);
ILibHTTPPacket_Stash_Put(packet, "_idleTimeoutHandler", -1, ILibDuktape_http_request_idleTimeout);
}
if (duk_has_prop_string(ctx, 0, "headers"))
{
duk_get_prop_string(ctx, 0, "headers");
@@ -1750,10 +1815,66 @@ duk_ret_t ILibDuktape_http_request_no_op(duk_context *ctx)
{
return 0;
}
void ILibDuktape_http_request_connect(ILibWebClient_RequestToken token)
{
ILibWebClient_StateObject wcdo = ILibWebClient_GetStateObjectFromRequestToken(token);
void **user = ILibWebClient_RequestToken_GetUserObjects(token);
duk_context *ctx = (duk_context*)user[0];
ILibDuktape_http_requestClient_callbacks *ptr = (ILibDuktape_http_requestClient_callbacks*)user[1];
if (ctx != NULL && ptr != NULL && ptr->OnSocket != NULL)
{
duk_push_object(ctx); // [socket]
duk_push_pointer(ctx, wcdo); // [socket][wcdo]
duk_put_prop_string(ctx, -2, CLIENTREQUEST_SOCKET_WCDO); // [socket]
duk_push_heapptr(ctx, ptr->clientRequest); // [socket][clientRequest]
duk_dup(ctx, -2); // [socket][clientRequest][socket]
ILibDuktape_CreateReadonlyProperty(ctx, "socket"); // [socket][clientRequest]
duk_pop(ctx); // [socket]
duk_push_heapptr(ctx, ptr->clientRequest); // [socket][clientRequest]
ILibDuktape_Push_ObjectStash(ctx); // [socket][clientRequest][stash]
duk_dup(ctx, -3); // [socket][clientRequest][stash][socket]
duk_put_prop_string(ctx, -2, Duktape_GetStashKey(wcdo)); // [socket][clientRequest][stash]
duk_pop_2(ctx); // [socket]
ILibDuktape_EventEmitter *emitter = ILibDuktape_EventEmitter_Create(ctx);
ILibDuktape_EventEmitter_CreateEventEx(emitter, "end");
duk_push_heapptr(ctx, ptr->OnSocket); // [socket][OnSocket]
duk_push_heapptr(ctx, ptr->clientRequest); // [socket][OnSocket][this]
duk_dup(ctx, -3); // [socket][OnSocket][this][socket]
if (duk_pcall_method(ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "http.request_connect.onSocket(): "); }
duk_pop_2(ctx); // ...
}
}
void ILibDuktape_http_request_disconnect(ILibWebClient_RequestToken token)
{
ILibWebClient_StateObject wcdo = ILibWebClient_GetStateObjectFromRequestToken(token);
char *key = Duktape_GetStashKey(wcdo);
void **user = ILibWebClient_RequestToken_GetUserObjects(token);
if (user == NULL) { return; }
duk_context *ctx = (duk_context*)user[0];
ILibDuktape_http_requestClient_callbacks *ptr = (ILibDuktape_http_requestClient_callbacks*)user[1];
if (ctx != NULL && ptr != NULL)
{
duk_push_heapptr(ctx, ptr->clientRequest); // [clientRequest]
ILibDuktape_Push_ObjectStash(ctx); // [clientRequest][stash]
if (duk_has_prop_string(ctx, -1, key))
{
duk_get_prop_string(ctx, -1, key); // [clientRequest][stash][socket]
duk_get_prop_string(ctx, -1, "emit"); // [clientRequest][stash][socket][emit]
duk_swap_top(ctx, -2); // [clientRequest][stash][emit][this]
duk_push_string(ctx, "end"); // [clientRequest][stash][emit][this][end]
if (duk_pcall_method(ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "http.request_disconnect(): "); }
duk_pop(ctx); // [clientRequest][stash]
duk_del_prop_string(ctx, -2, key);
}
duk_pop_2(ctx); // ...
}
}
void* ILibDuktape_http_request_PUSH_clientRequest(duk_context *ctx, ILibWebClient_RequestToken token, int isWebSocket)
{
ILibDuktape_EventEmitter *emitter = NULL;
void **user = ILibWebClient_RequestToken_GetUserObjects_Tail(token);
void **user = ILibWebClient_RequestToken_GetUserObjects(token);
if (user[1] != NULL && ((ILibDuktape_http_request_dataType*)user[1])->STRUCT_TYPE == ILibDuktape_http_request_dataType_request &&
((ILibDuktape_http_requestClient_callbacks*)user[1])->clientRequest != NULL)
@@ -1762,6 +1883,11 @@ void* ILibDuktape_http_request_PUSH_clientRequest(duk_context *ctx, ILibWebClien
return(user[1]);
}
if (isWebSocket == 0)
{
ILibWebClient_RequestToken_ConnectionHandler_Set(token, ILibDuktape_http_request_connect, ILibDuktape_http_request_disconnect);
}
duk_push_object(ctx); // [obj]
duk_push_pointer(ctx, user);
duk_put_prop_string(ctx, -2, HTTP_REQUEST_USER_PTR);
@@ -1783,6 +1909,9 @@ void* ILibDuktape_http_request_PUSH_clientRequest(duk_context *ctx, ILibWebClien
{
ILibDuktape_EventEmitter_CreateEvent(emitter, "response", &(((ILibDuktape_http_requestClient_callbacks*)user[1])->OnReceive));
ILibDuktape_EventEmitter_CreateEvent(emitter, "continue", &(((ILibDuktape_http_requestClient_callbacks*)user[1])->OnContinue));
ILibDuktape_EventEmitter_CreateEvent(emitter, "socket", &(((ILibDuktape_http_requestClient_callbacks*)user[1])->OnSocket));
ILibDuktape_EventEmitter_CreateEventEx(emitter, "timeout");
((ILibDuktape_http_requestClient_callbacks*)user[1])->requestStream = ILibDuktape_WritableStream_Init(ctx, ILibDuktape_http_request_write, ILibDuktape_http_request_end, token);
((ILibDuktape_http_requestClient_callbacks*)user[1])->clientRequest = duk_get_heapptr(ctx, -1);
}
@@ -2433,6 +2562,14 @@ duk_ret_t ILibDuktape_httpDigest_clientRequest_response2(duk_context *ctx)
duk_dup(ctx, 0); // [emit][this][response][imsg]
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "http-digest: Error dispatching response event"); }
}
else
{
duk_get_prop_string(ctx, -1, "emit"); // [digestClientRequest][emit]
duk_swap_top(ctx, -2); // [emit][this]
duk_push_string(ctx, "error"); // [emit][this][response]
duk_dup(ctx, 0); // [emit][this][response][imsg]
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "http-digest: Error dispatching response event"); }
}
return(0);
}
@@ -2469,15 +2606,81 @@ duk_ret_t ILibDuktape_httpDigest_clientRequest_propagateEvent(duk_context *ctx)
}
extern void* ILibWebClient_Digest_GenerateTable(ILibWebClient_StateObject state);
void ILibDuktape_httpDigest_clientRequest_IncomingMessage_PauseHandler(ILibDuktape_readableStream *sender, void *user)
{
duk_push_heapptr(sender->ctx, user); // [imsg]
duk_get_prop_string(sender->ctx, -1, "pause"); // [imsg][pause]
duk_swap_top(sender->ctx, -2); // [pause][this]
if (duk_pcall_method(sender->ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(sender->ctx, "ILibDuktape_httpDigest_clientRequest_IncomingMessage_PauseHandler: Error Invoking Pause on ClientRequest: "); }
duk_pop(sender->ctx); // ...
}
void ILibDuktape_httpDigest_clientRequest_IncomingMessage_ResumeHandler(ILibDuktape_readableStream *sender, void *user)
{
duk_push_heapptr(sender->ctx, user); // [imsg]
duk_get_prop_string(sender->ctx, -1, "resume"); // [imsg][pause]
duk_swap_top(sender->ctx, -2); // [pause][this]
if (duk_pcall_method(sender->ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(sender->ctx, "ILibDuktape_httpDigest_clientRequest_IncomingMessage_ResumeHandler: Error Invoking Resume on ClientRequest: "); }
duk_pop(sender->ctx); // ...
}
duk_ret_t ILibDuktape_httpDigest_clientRequest_OnData(duk_context *ctx)
{
duk_push_current_function(ctx);
duk_get_prop_string(ctx, -1, CLIENTREQUEST_IMSG_RSPTR);
ILibDuktape_readableStream *rs = (ILibDuktape_readableStream*)duk_get_pointer(ctx, -1);
duk_size_t bufferLen;
char *buffer;
buffer = Duktape_GetBuffer(ctx, 0, &bufferLen);
ILibDuktape_readableStream_WriteData(rs, buffer, (int)bufferLen);
return(0);
}
duk_ret_t ILibDuktape_httpDigest_clientRequest_OnEnd(duk_context *ctx)
{
duk_push_current_function(ctx);
duk_get_prop_string(ctx, -1, CLIENTREQUEST_IMSG_RSPTR);
ILibDuktape_readableStream *rs = (ILibDuktape_readableStream*)duk_get_pointer(ctx, -1);
ILibDuktape_readableStream_WriteEnd(rs);
return(0);
}
duk_ret_t ILibDuktape_httpDigest_http_request_socketEvent_end(duk_context *ctx)
{
duk_push_this(ctx); // [socket]
duk_get_prop_string(ctx, -1, CLIENTREQUEST_SOCKET_WCDO);// [socket][wcdo]
duk_get_prop_string(ctx, -2, DIGEST_CLIENT_REQUEST); // [socket][wcdo][digest]
duk_get_prop_string(ctx, -1, DIGEST_WCDO); // [socket][wcdo][digest][wcdo]
if (duk_get_pointer(ctx, -1) == duk_get_pointer(ctx, -3))
{
duk_del_prop_string(ctx, -2, DIGEST_WCDO);
}
return(0);
}
duk_ret_t ILibDuktape_httpDigest_http_request_socketEvent(duk_context *ctx)
{
duk_push_this(ctx); // [clientRequest]
duk_get_prop_string(ctx, -1, DIGEST_CLIENT_REQUEST); // [clientRequest][digestClientRequest]
duk_get_prop_string(ctx, -1, DIGESTCLIENTREQUEST_DIGEST); // [clientRequest][digestClientRequest][digest]
duk_get_prop_string(ctx, 0, CLIENTREQUEST_SOCKET_WCDO); // [clientRequest][digestClientRequest][digest][wcdo]
duk_put_prop_string(ctx, -2, DIGEST_WCDO); // [clientRequest][digestClientRequest][digest]
duk_dup(ctx, 0); // [clientRequest][digestClientRequest][digest][socket]
duk_swap_top(ctx, -2); // [clientRequest][digestClientRequest][socket][digest]
duk_put_prop_string(ctx, -2, DIGEST_CLIENT_REQUEST); // [clientRequest][digestClientRequest][socket]
ILibDuktape_EventEmitter_AddOnceEx(ILibDuktape_EventEmitter_GetEmitter(ctx, 0), "end", ILibDuktape_httpDigest_http_request_socketEvent_end, 0);
return(0);
}
duk_ret_t ILibDuktape_httpDigest_clientRequest_response(duk_context *ctx)
{
ILibHTTPPacket *packet;
ILibWebClient_StateObject wcdo;
char *username, *password;
int tmpLen = 0;
char *uri = NULL;
void *digestClientPtr;
void *paramPtr = NULL;
void *cr_self;
duk_push_current_function(ctx);
duk_get_prop_string(ctx, -1, "digestClientRequest");
@@ -2494,7 +2697,8 @@ duk_ret_t ILibDuktape_httpDigest_clientRequest_response(duk_context *ctx)
if (packet->StatusCode == 401)
{
duk_push_heapptr(ctx, digestClientPtr); // [digestClientRequest]
if (duk_has_prop_string(ctx, -1, DIGEST_CLIENT_REQUEST))
int endCalledAlready = Duktape_GetBooleanProperty(ctx, -1, DIGESTCLIENTREQUEST_END_CALLED, 0);
if (endCalledAlready == 0 && duk_has_prop_string(ctx, -1, DIGEST_CLIENT_REQUEST))
{
duk_get_prop_string(ctx, -1, DIGEST_CLIENT_REQUEST); // [digestClientRequest][clientRequest]
duk_get_prop_string(ctx, -1, "end"); // [digestClientRequest][clientRequest][end]
@@ -2508,16 +2712,14 @@ duk_ret_t ILibDuktape_httpDigest_clientRequest_response(duk_context *ctx)
duk_get_prop_string(ctx, 0, HTTP_INCOMINGMSG_WebStateObject);
wcdo = (ILibWebClient_StateObject)duk_get_pointer(ctx, -1);
int freePath = 0;
char *method, *path;
char result1[33];
char result2[33];
char result3[33];
void* table = ILibWebClient_Digest_GenerateTable(wcdo);
char* realm = (char*)ILibGetEntry(table, "realm", 5);
char* nonce = (char*)ILibGetEntry(table, "nonce", 5);
char* opaque = (char*)ILibGetEntry(table, "opaque", 6);
ILibDestroyHashTree(table);
duk_size_t methodLen, pathLen;
int authLen;
char *method, *path, *auth;
void *ReservedMemory = ILibMemory_AllocateA(8000);
ILibHTTPPacket *pk = ILibCreateEmptyPacketEx(ReservedMemory);
pk->Version = "1.1";
pk->VersionLength = 3;
duk_push_this(ctx); // [clientRequest]
duk_get_prop_string(ctx, -1, HTTP_CLIENTREQUEST_PARAMETER); // [clientRequest][param]
@@ -2528,30 +2730,24 @@ duk_ret_t ILibDuktape_httpDigest_clientRequest_response(duk_context *ctx)
unsigned short tmpPort;
uri = (char*)duk_get_string(ctx, -1);
ILibParseUri(uri, &tmpHost, &tmpPort, &path, NULL);
tmpLen = sprintf_s(ILibScratchPad2, sizeof(ILibScratchPad2), "%s:%s", (method = "GET"), path);
util_md5hex(ILibScratchPad2, tmpLen, result2);
ILibSetDirective(pk, "GET", 3, path, -1);
free(tmpHost);
freePath = 1;
free(path);
}
else
{
tmpLen = sprintf_s(ILibScratchPad2, sizeof(ILibScratchPad2), "%s:%s", (method = Duktape_GetStringPropertyValue(ctx, -1, "method", "GET")), (path = Duktape_GetStringPropertyValue(ctx, -1, "path", "/")));
util_md5hex(ILibScratchPad2, tmpLen, result2);
method = (char*)Duktape_GetStringPropertyValueEx(ctx, -1, "method", "GET", &methodLen);
path = (char*)Duktape_GetStringPropertyValueEx(ctx, -1, "path", "/", &pathLen);
ILibSetDirective(pk, method, (int)methodLen, path, (int)pathLen);
paramPtr = duk_get_heapptr(ctx, -1);
}
tmpLen = sprintf_s(ILibScratchPad2, sizeof(ILibScratchPad2), "%s:%s:%s", username, realm, password);
util_md5hex(ILibScratchPad2, tmpLen, result1);
tmpLen = sprintf_s(ILibScratchPad2, sizeof(ILibScratchPad2), "%s:%s:%s", result1, nonce, result2);
util_md5hex(ILibScratchPad2, tmpLen, result3);
tmpLen = sprintf_s(ILibScratchPad2, sizeof(ILibScratchPad2), "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", opaque=\"%s\", response=\"%s\"", username, realm, nonce, path, opaque, result3);
ILibWebClient_GenerateAuthenticationHeader(wcdo, pk, username, password);
auth = ILibGetHeaderLineEx(pk, "Authorization", 13, &authLen);
duk_push_this(ctx); // [clientReqeust]
duk_get_prop_string(ctx, -1, CLIENTREQUEST_HTTP); // [clientReqeust][http]
if (freePath != 0) { free(path); }
if (paramPtr == NULL)
{
@@ -2566,6 +2762,7 @@ duk_ret_t ILibDuktape_httpDigest_clientRequest_response(duk_context *ctx)
duk_get_prop_string(ctx, -1, "request"); // [clientRequest][http][request]
duk_swap_top(ctx, -2); // [clientRequest][request][this]
duk_push_heapptr(ctx, paramPtr); // [clientRequest][request][this][options]
duk_del_prop_string(ctx, -1, "timeout");
}
if(!duk_has_prop_string(ctx, -1, "headers"))
@@ -2577,7 +2774,7 @@ duk_ret_t ILibDuktape_httpDigest_clientRequest_response(duk_context *ctx)
duk_get_prop_string(ctx, -1, "headers"); // [clientReqeust][get][this][options][headers]
}
duk_push_lstring(ctx, ILibScratchPad2, tmpLen); // [clientReqeust][get][this][options][headers][Auth]
duk_push_lstring(ctx, auth, authLen); // [clientReqeust][get][this][options][headers][Auth]
duk_put_prop_string(ctx, -2, "Authorization"); // [clientReqeust][get][this][options][headers]
duk_put_prop_string(ctx, -2, "headers"); // [clientReqeust][get][this][options]
duk_push_c_function(ctx, ILibDuktape_httpDigest_clientRequest_response2, DUK_VARARGS); // [clientReqeust][get][this][options][callback]
@@ -2585,7 +2782,9 @@ duk_ret_t ILibDuktape_httpDigest_clientRequest_response(duk_context *ctx)
duk_put_prop_string(ctx, -2, "digestClientRequest"); // [clientReqeust][get][this][options][callback]
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "digest_onResponse: Error Invoking http.get"); }
duk_push_heapptr(ctx, digestClientPtr); // [clientRequest][digestClientRequest]
duk_put_prop_string(ctx, -2, DIGEST_CLIENT_REQUEST); // [clientRequest]
ILibDuktape_EventEmitter_AddOnceEx2(ctx, -1, "socket", ILibDuktape_httpDigest_http_request_socketEvent, 1);
duk_push_c_function(ctx, ILibDuktape_httpDigest_clientRequest_propagateEvent, DUK_VARARGS); // [clientReqeust][EventDispatcher]
duk_push_heapptr(ctx, digestClientPtr); // [clientReqeust][EventDispatcher][digestClientRequest]
@@ -2612,17 +2811,87 @@ duk_ret_t ILibDuktape_httpDigest_clientRequest_response(duk_context *ctx)
ILibDuktape_EventEmitter_AddOnce(ILibDuktape_EventEmitter_GetEmitter(ctx, -2), "continue", duk_get_heapptr(ctx, -1));
duk_pop(ctx); // [clientReqeust]
duk_push_c_function(ctx, ILibDuktape_httpDigest_clientRequest_propagateEvent, DUK_VARARGS); // [clientReqeust][EventDispatcher]
duk_push_heapptr(ctx, digestClientPtr); // [clientReqeust][EventDispatcher][digestClientRequest]
duk_put_prop_string(ctx, -2, DIGEST_CLIENT_REQUEST); // [clientReqeust][EventDispatcher]
duk_push_string(ctx, "timeout"); // [clientReqeust][EventDispatcher][eventName]
duk_put_prop_string(ctx, -2, CLIENTREQUEST_EVENT_NAME); // [clientReqeust][EventDispatcher]
ILibDuktape_EventEmitter_AddOnce(ILibDuktape_EventEmitter_GetEmitter(ctx, -2), "timeout", duk_get_heapptr(ctx, -1));
duk_pop(ctx); // [clientReqeust]
duk_push_c_function(ctx, ILibDuktape_httpDigest_clientRequest_onDrain, DUK_VARARGS); // [clientReqeust][onDrain]
duk_push_heapptr(ctx, digestClientPtr); // [clientReqeust][onDrain][digestClientRequest]
duk_put_prop_string(ctx, -2, DIGEST_CLIENT_REQUEST); // [clientReqeust][onDrain]
ILibDuktape_EventEmitter_AddOn(ILibDuktape_EventEmitter_GetEmitter(ctx, -2), "drain", duk_get_heapptr(ctx, -1));
duk_pop(ctx); // [clientReqeust]
if (endCalledAlready != 0)
{
duk_push_heapptr(ctx, digestClientPtr);
if (duk_has_prop_string(ctx, -1, DIGESTCLIENTREQUEST_TmpBuffer))
{
duk_get_prop_string(ctx, -1, DIGESTCLIENTREQUEST_TmpBuffer); // [clientReqeust][digestClientRequest][buffer]
duk_swap_top(ctx, -2); // [clientRequesat][buffer][digestClientRequest]
duk_pop(ctx); // [clientRequest][buffer]
duk_dup(ctx, -2); // [clientRequest][buffer][clientRequest]
duk_get_prop_string(ctx, -1, "write"); // [clientRequest][buffer][clientRequest][write]
duk_swap_top(ctx, -2); // [clientRequest][buffer][write][this]
duk_swap(ctx, -3, -2); // [clientRequest][write][buffer][this]
duk_swap_top(ctx, -2); // [clientReqeust][write][this][buffer]
if (duk_pcall_method(ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "httpDigest.clientRequest.onResponse(): Error calling clientRequest.write(): "); }
duk_pop(ctx); // [clientRequest]
}
else
{
duk_pop(ctx); // [clientRequest]
}
duk_dup(ctx, -1); // [clientReqeust][clientReqeust]
duk_get_prop_string(ctx, -1, "end"); // [clientReqeust][clientReqeust][end]
duk_swap_top(ctx, -2); // [clientReqeust][end][this]
if (duk_pcall_method(ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "httpDigest.onResponse(): Error invoking ClientRequest.end(): "); }
duk_pop(ctx); // [clientRequest]
}
duk_push_heapptr(ctx, digestClientPtr); // [clientRequest][digestClientRequest]
duk_swap_top(ctx, -2); // [digestClientRequest][clientRequest]
duk_put_prop_string(ctx, -2, DIGEST_CLIENT_REQUEST); // [digestClientRequest]
}
else
{
duk_dup(ctx, 0);
cr_self = duk_get_heapptr(ctx, -1);
duk_pop(ctx);
duk_push_heapptr(ctx, digestClientPtr); // [digestClientRequest]
duk_get_prop_string(ctx, -1, "emit"); // [digestClientRequest][emit]
duk_swap_top(ctx, -2); // [emit][this]
duk_push_string(ctx, "response"); // [emit][this][response]
ILibDuktape_http_server_PUSH_IncomingMessage(ctx, packet, NULL); // [emit][this][response][imsg]
ILibDuktape_readableStream *rs = ILibDuktape_ReadableStream_Init(ctx, ILibDuktape_httpDigest_clientRequest_IncomingMessage_PauseHandler, ILibDuktape_httpDigest_clientRequest_IncomingMessage_ResumeHandler, cr_self);
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "digestClientRequest.onResponse(): "); }
duk_pop(ctx); // ...
duk_dup(ctx, 0); // [imsg]
duk_get_prop_string(ctx, -1, "on"); // [imsg][on]
duk_swap_top(ctx, -2); // [on][this]
duk_push_string(ctx, "data"); // [on][this][data]
duk_push_c_function(ctx, ILibDuktape_httpDigest_clientRequest_OnData, DUK_VARARGS); // [on][this][data][func]
duk_push_pointer(ctx, rs); // [on][this][data][func][ptr]
duk_put_prop_string(ctx, -2, CLIENTREQUEST_IMSG_RSPTR); // [on][this][data][func]
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "digestClientRequst.onResponse(): Error attaching event to clientRequest.on('data'): "); }
duk_pop(ctx);
duk_dup(ctx, 0); // [imsg]
duk_get_prop_string(ctx, -1, "on"); // [imsg][on]
duk_swap_top(ctx, -2); // [on][this]
duk_push_string(ctx, "end"); // [on][this][end]
duk_push_c_function(ctx, ILibDuktape_httpDigest_clientRequest_OnEnd, DUK_VARARGS); // [on][this][end][func]
duk_push_pointer(ctx, rs); // [on][this][end][func][ptr]
duk_put_prop_string(ctx, -2, CLIENTREQUEST_IMSG_RSPTR); // [on][this][end][func]
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "digestClientRequst.onResponse(): Error attaching event to clientRequest.on('end'): "); }
duk_pop(ctx);
}
return(0);
}
duk_ret_t ILibDuktape_httpDigest_clientRequest_setter(duk_context *ctx)
@@ -2674,6 +2943,30 @@ ILibTransport_DoneState ILibDuktape_httpDigest_http_request_WriteHandler(struct
duk_context *ctx = stream->ctx;
duk_push_heapptr(ctx, stream->obj); // [digestClientRequest]
if (Duktape_GetBooleanProperty(ctx, -1, DIGESTCLIENTREQUEST_CONTINUE, 0) == 0)
{
duk_size_t bufLen;
char *tmpBuffer;
if (duk_has_prop_string(ctx, -1, DIGESTCLIENTREQUEST_TmpBuffer))
{
duk_get_prop_string(ctx, -1, DIGESTCLIENTREQUEST_TmpBuffer); // [digestClientRequest][oldBuffer]
bufLen = duk_get_length(ctx, -1);
duk_resize_buffer(ctx, -1, bufLen + bufferLen);
tmpBuffer = (char*)Duktape_GetBuffer(ctx, -1, &bufLen);
memcpy_s(tmpBuffer + bufLen - (size_t)bufferLen, (size_t)bufferLen, buffer, (size_t)bufferLen);
duk_pop(ctx); // [digestClientRequest]
}
else
{
duk_push_dynamic_buffer(ctx, (duk_size_t)bufferLen); // [digestClientRequest][buffer]
tmpBuffer = (char*)Duktape_GetBuffer(ctx, -1, &bufLen);
duk_put_prop_string(ctx, -2, DIGESTCLIENTREQUEST_TmpBuffer); // [digestClientRequest]
memcpy_s(tmpBuffer, bufLen, buffer, (size_t)bufferLen);
}
}
if (duk_has_prop_string(ctx, -1, DIGEST_CLIENT_REQUEST))
{
duk_get_prop_string(ctx, -1, DIGEST_CLIENT_REQUEST); // [digestClientRequest][clientRequest]
@@ -2710,6 +3003,9 @@ void ILibDuktape_httpDigest_http_request_DoneHandler(struct ILibDuktape_Writable
duk_context *ctx = stream->ctx;
duk_push_heapptr(ctx, stream->obj); // [digestClientRequest]
duk_push_true(ctx);
duk_put_prop_string(ctx, -2, DIGESTCLIENTREQUEST_END_CALLED);
if (duk_has_prop_string(ctx, -1, DIGEST_CLIENT_REQUEST))
{
duk_get_prop_string(ctx, -1, DIGEST_CLIENT_REQUEST); // [digestClientRequest][clientRequest]
@@ -2722,16 +3018,33 @@ void ILibDuktape_httpDigest_http_request_DoneHandler(struct ILibDuktape_Writable
}
duk_pop(ctx); // ...
}
duk_ret_t ILibDuktape_httpDigest_http_request_continueOccured(duk_context *ctx)
{
duk_push_this(ctx); // [digestClientRequest]
duk_push_true(ctx);
duk_put_prop_string(ctx, -2, DIGESTCLIENTREQUEST_CONTINUE);
return(0);
}
duk_ret_t ILibDuktape_httpDigest_http_request(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
void *clientRequest = NULL;
ILibDuktape_EventEmitter *emitter;
ILibDuktape_EventEmitter *crEmitter;
char *username = NULL;
char *password = NULL;
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "isGet"); // [func][isGet]
duk_push_this(ctx); // [func][isGet][digest]
duk_get_prop_string(ctx, -1, DIGEST_USERNAME); // [func][isGet][digest][username]
duk_get_prop_string(ctx, -2, DIGEST_PASSWORD); // [func][isGet][digest][username][password]
username = (char*)duk_get_string(ctx, -2);
password = (char*)duk_get_string(ctx, -1);
duk_pop_2(ctx); // [func][isGet][digest]
duk_get_prop_string(ctx, -1, HTTP_DIGEST); // [func][isGet][digest][http]
if (duk_get_int(ctx, -3) != 0)
{
@@ -2744,6 +3057,46 @@ duk_ret_t ILibDuktape_httpDigest_http_request(duk_context *ctx)
duk_swap_top(ctx, -2); // [func][isGet][digest][get/request][this]
duk_dup(ctx, 0); // [func][isGet][digest][get/request][this][param1]
//
// Check to see if we can insert Auth Headers, in case we already authenticated
//
if (duk_has_prop_string(ctx, -4, DIGEST_WCDO))
{
void *wcdo = NULL;
ILibHTTPPacket *pk = ILibCreateEmptyPacketEx(ILibMemory_AllocateA(4096));
duk_size_t methodLen, pathLen;
char *method, *path;
pk->Version = "1.1";
pk->VersionLength = 3;
method = (char*)Duktape_GetStringPropertyValueEx(ctx, -1, "method", "GET", &methodLen);
path = (char*)Duktape_GetStringPropertyValueEx(ctx, -1, "path", "/", &pathLen);
ILibSetDirective(pk, method, (int)methodLen, path, (int)pathLen);
duk_get_prop_string(ctx, -4, DIGEST_WCDO);
wcdo = duk_get_pointer(ctx, -1);
duk_pop(ctx);
ILibWebClient_GenerateAuthenticationHeader(wcdo, pk, username, password);
char *auth = ILibGetHeaderLine(pk, "Authorization", 13);
if (auth != NULL)
{
if (duk_has_prop_string(ctx, -1, "headers")) // [func][isGet][digest][get/request][this][param1]
{
duk_get_prop_string(ctx, -1, "headers"); // [func][isGet][digest][get/request][this][param1][headers]
}
else
{
duk_push_object(ctx); // [func][isGet][digest][get/request][this][param1][headers]
duk_dup(ctx, -1); // [func][isGet][digest][get/request][this][param1][headers][headers]
duk_put_prop_string(ctx, -3, "headers"); // [func][isGet][digest][get/request][this][param1][headers]
}
duk_push_string(ctx, auth); // [func][isGet][digest][get/request][this][param1][headers][auth]
duk_put_prop_string(ctx, -2, "Authorization"); // [func][isGet][digest][get/request][this][param1][headers]
duk_pop(ctx); // [func][isGet][digest][get/request][this][param1]
}
}
if (duk_pcall_method(ctx, 1) != 0) { duk_throw(ctx); return(DUK_RET_ERROR); }
// [clientRequest]
clientRequest = duk_get_heapptr(ctx, -1);
@@ -2755,6 +3108,8 @@ duk_ret_t ILibDuktape_httpDigest_http_request(duk_context *ctx)
duk_push_c_function(ctx, ILibDuktape_httpDigest_clientRequest_response, DUK_VARARGS); // [once][this][response][method]
duk_push_object(ctx); // [once][this][response][method][digest-clientRequest]
duk_push_this(ctx); // [once][this][response][method][digest-clientRequest][digest]
duk_put_prop_string(ctx, -2, DIGESTCLIENTREQUEST_DIGEST); // [once][this][response][method][digest-clientRequest]
duk_push_heapptr(ctx, clientRequest); // [once][this][response][method][digest-clientRequest][clientRequest]
duk_dup(ctx, -2); // [once][this][response][method][digest-clientRequest][clientRequest][digest-clientRequest]
duk_put_prop_string(ctx, -2, DIGEST_CLIENT_REQUEST); // [once][this][response][method][digest-clientRequest][clientRequest]
@@ -2764,6 +3119,10 @@ duk_ret_t ILibDuktape_httpDigest_http_request(duk_context *ctx)
ILibDuktape_EventEmitter_CreateEventEx(emitter, "error");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "upgrade");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "continue");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "timeout");
ILibDuktape_EventEmitter_AddOnceEx(emitter, "continue", ILibDuktape_httpDigest_http_request_continueOccured, 0);
ILibDuktape_EventEmitter_AddOnceEx(crEmitter, "socket", ILibDuktape_httpDigest_http_request_socketEvent, 1);
ILibDuktape_WritableStream_Init(ctx, ILibDuktape_httpDigest_http_request_WriteHandler, ILibDuktape_httpDigest_http_request_DoneHandler, NULL);
@@ -2803,6 +3162,14 @@ duk_ret_t ILibDuktape_httpDigest_http_request(duk_context *ctx)
ILibDuktape_EventEmitter_AddOnce(crEmitter, "continue", duk_get_heapptr(ctx, -1)); // [digestClientRequest][EventDispatcher]
duk_pop(ctx); // [digestClientRequest]
duk_push_c_function(ctx, ILibDuktape_httpDigest_clientRequest_propagateEvent, DUK_VARARGS); // [digestClientRequest][EventDispatcher]
duk_dup(ctx, -2); // [digestClientRequest][EventDispatcher][digestClientRequest]
duk_put_prop_string(ctx, -2, DIGEST_CLIENT_REQUEST); // [digestClientRequest][EventDispatcher]
duk_push_string(ctx, "timeout"); // [digestClientRequest][EventDispatcher][eventName]
duk_put_prop_string(ctx, -2, CLIENTREQUEST_EVENT_NAME); // [digestClientRequest][EventDispatcher]
ILibDuktape_EventEmitter_AddOnce(crEmitter, "timeout", duk_get_heapptr(ctx, -1)); // [digestClientRequest][EventDispatcher]
duk_pop(ctx); // [digestClientRequest]
duk_push_c_function(ctx, ILibDuktape_httpDigest_clientRequest_onDrain, DUK_VARARGS); // [digestClientRequest][onDrain]
duk_dup(ctx, -2); // [digestClientRequest][onDrain][digestClientRequest]
duk_put_prop_string(ctx, -2, DIGEST_CLIENT_REQUEST); // [digestClientRequest][onDrain]

View File

@@ -24,6 +24,7 @@ limitations under the License.
#include "microstack/ILibAsyncSocket.h"
#include "microstack/ILibCrypto.h"
#include "microstack/ILibAsyncServerSocket.h"
#include "microstack/ILibRemoteLogging.h"
typedef struct ILibDuktape_net_socket
{
@@ -264,6 +265,7 @@ duk_ret_t ILibDuktape_net_socket_address(duk_context *ctx)
duk_push_string(ctx, ILibInet_ntop2((struct sockaddr*)&local, ILibScratchPad, sizeof(ILibScratchPad)));
duk_put_prop_string(ctx, -2, "address");
return 1;
}
@@ -918,6 +920,29 @@ duk_ret_t ILibDuktape_net_server_Finalizer(duk_context *ctx)
return 0;
}
duk_ret_t ILibDuktape_net_server_address(duk_context *ctx)
{
duk_push_this(ctx); // [server]
duk_get_prop_string(ctx, -1, ILibDuktape_net_Server_buffer); // [server][buffer]
ILibDuktape_net_server *server = (ILibDuktape_net_server*)Duktape_GetBuffer(ctx, -1, NULL);
struct sockaddr_in6 local;
memset(&local, 0, sizeof(struct sockaddr_in6));
ILibAsyncServerSocket_GetLocal(server->server, (struct sockaddr*)&local, sizeof(struct sockaddr_in6));
if (local.sin6_family == AF_UNSPEC) { return(ILibDuktape_Error(ctx, "net.server.address(): call to getsockname() failed")); }
duk_push_object(ctx);
duk_push_string(ctx, local.sin6_family == AF_INET6 ? "IPv6" : "IPv4");
duk_put_prop_string(ctx, -2, "family");
duk_push_int(ctx, (int)ntohs(local.sin6_port));
duk_put_prop_string(ctx, -2, "port");
duk_push_string(ctx, ILibRemoteLogging_ConvertAddress((struct sockaddr*)&local));
duk_put_prop_string(ctx, -2, "address");
return(1);
}
duk_ret_t ILibDuktape_net_createServer(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
@@ -939,6 +964,7 @@ duk_ret_t ILibDuktape_net_createServer(duk_context *ctx)
ILibDuktape_EventEmitter_CreateEvent(server->emitter, "listening", &(server->OnListening));
ILibDuktape_CreateInstanceMethod(ctx, "listen", ILibDuktape_net_server_listen, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "address", ILibDuktape_net_server_address, 0);
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_net_server_Finalizer);
for (i = 0; i < 2 && i < nargs; ++i)

View File

@@ -261,6 +261,39 @@ int ILibDuktape_EventEmitter_AddOnce(ILibDuktape_EventEmitter *emitter, char *ev
return retVal;
}
int ILibDuktape_EventEmitter_AddOnceEx2(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func, duk_idx_t funcArgs)
{
int retVal = 1;
duk_dup(ctx, idx); // [obj]
ILibDuktape_Push_ObjectStash(ctx); // [obj][stash]
duk_push_c_function(ctx, func, funcArgs); // [obj][stash][func]
duk_dup(ctx, -1); // [obj][stash][func][func]
duk_put_prop_string(ctx, -3, Duktape_GetStashKey(duk_get_heapptr(ctx, -1))); // [obj][stash][func]
duk_get_prop_string(ctx, -3, "once"); // [obj][stash][func][once]
duk_swap(ctx, -3, -1); // [obj][once][func][stash]
duk_swap(ctx, -4, -3); // [once][this][func][stash]
duk_pop(ctx); // [once][this][func]
duk_push_string(ctx, eventName); // [once][this][func][eventName]
duk_swap_top(ctx, -2); // [once][this][eventName][func]
retVal = duk_pcall_method(ctx, 2); // [retVal]
duk_pop(ctx); // ...
return(retVal);
}
int ILibDuktape_EventEmitter_AddOnceEx(ILibDuktape_EventEmitter *emitter, char *eventName, duk_c_function func, duk_idx_t funcArgs)
{
int retVal = 1;
duk_push_heapptr(emitter->ctx, emitter->object); // [obj]
ILibDuktape_Push_ObjectStash(emitter->ctx); // [obj][stash]
duk_push_c_function(emitter->ctx, func, funcArgs); // [obj][stash][func]
retVal = ILibDuktape_EventEmitter_AddOnce(emitter, eventName, duk_get_heapptr(emitter->ctx, -1));
duk_put_prop_string(emitter->ctx, -2, Duktape_GetStashKey(duk_get_heapptr(emitter->ctx, -1))); // [obj][stash]
duk_pop_2(emitter->ctx); // ...
return(retVal);
}
int ILibDuktape_EventEmitter_AddOn(ILibDuktape_EventEmitter *emitter, char *eventName, void *heapptr)
{
int retVal = 1;

View File

@@ -715,6 +715,14 @@ ILibAsyncServerSocket_ServerModule ILibCreateAsyncServerSocketModuleWithMemory(v
return RetVal;
}
void ILibAsyncServerSocket_GetLocal(ILibAsyncServerSocket_ServerModule ServerSocketModule, struct sockaddr* addr, size_t addrLen)
{
socklen_t ssize = (socklen_t)addrLen;
if (getsockname(((struct ILibAsyncServerSocketModule*)ServerSocketModule)->ListenSocket, addr, &ssize) != 0)
{
((struct sockaddr_in6*)addr)->sin6_family = AF_UNSPEC;
}
}
/*! \fn ILibAsyncServerSocket_GetPortNumber(ILibAsyncServerSocket_ServerModule ServerSocketModule)
\brief Returns the port number the server is bound to
\param ServerSocketModule The ILibAsyncServer to query

View File

@@ -134,6 +134,7 @@ void ILibAsyncServerSocket_StopListening(ILibAsyncServerSocket_ServerModule modu
void ILibAsyncServerSocket_ResumeListening(ILibAsyncServerSocket_ServerModule module);
unsigned short ILibAsyncServerSocket_GetPortNumber(ILibAsyncServerSocket_ServerModule ServerSocketModule);
void ILibAsyncServerSocket_GetLocal(ILibAsyncServerSocket_ServerModule ServerSocketModule, struct sockaddr* addr, size_t addrLen);
/*! \def ILibAsyncServerSocket_Send
\brief Sends data onto the TCP stream

View File

@@ -962,7 +962,7 @@ void ILibAsyncSocket_ConnectToProxy(void* socketModule, struct sockaddr *localIn
ILibAsyncSocket_ConnectTo(socketModule, localInterface, remoteAddress, InterruptPtr, user);
}
#endif
#ifndef MICROSTACK_NOTLS
ILibAsyncSocket_SendStatus ILibAsyncSocket_ProcessEncryptedBuffer(ILibAsyncSocketModule *Reader)
{
int j;
@@ -1019,7 +1019,7 @@ ILibAsyncSocket_SendStatus ILibAsyncSocket_ProcessEncryptedBuffer(ILibAsyncSocke
sem_post(&(Reader->SendLock));
return retVal;
}
#endif
//
// Internal method called when data is ready to be processed on an ILibAsyncSocket
//
@@ -1342,10 +1342,10 @@ void ILibAsyncSocket_SetUser3(ILibAsyncSocket_SocketModule socketModule, int use
((struct ILibAsyncSocketModule*)socketModule)->user3 = user3;
}
void ILibAsyncSocket_SetTimeout(ILibAsyncSocket_SocketModule socketModule, int timeoutSeconds, ILibAsyncSocket_TimeoutHandler timeoutHandler)
void ILibAsyncSocket_SetTimeoutEx(ILibAsyncSocket_SocketModule socketModule, int timeoutMilliseconds, ILibAsyncSocket_TimeoutHandler timeoutHandler)
{
struct ILibAsyncSocketModule *module = (struct ILibAsyncSocketModule*)socketModule;
module->timeout_milliSeconds = timeoutSeconds * 1000;
module->timeout_milliSeconds = timeoutMilliseconds;
module->timeout_handler = timeoutHandler;
}
@@ -1848,7 +1848,11 @@ void ILibAsyncSocket_PostSelect(void* socketModule, int slct, fd_set *readset, f
if (module->PendingSend_Head == NULL && bytesSent != -1) { TriggerSendOK = 1; }
SEM_TRACK(AsyncSocket_TrackUnLock("ILibAsyncSocket_PostSelect", 2, module);)
sem_post(&(module->SendLock));
#ifndef MICROSTACK_NOTLS
if (TriggerSendOK != 0 && (module->ssl == NULL || module->SSLConnect != 0))
#else
if (TriggerSendOK != 0)
#endif
{
module->OnSendOK(module, module->user);
if (module->Transport.SendOkPtr != NULL) { module->Transport.SendOkPtr(module); }

View File

@@ -234,7 +234,8 @@ int ILibAsyncSocket_IsIPv6LinkLocal(struct sockaddr *LocalAddress);
int ILibAsyncSocket_IsModuleIPv6LinkLocal(ILibAsyncSocket_SocketModule module);
typedef void(*ILibAsyncSocket_TimeoutHandler)(ILibAsyncSocket_SocketModule module, void *user);
void ILibAsyncSocket_SetTimeout(ILibAsyncSocket_SocketModule module, int timeoutSeconds, ILibAsyncSocket_TimeoutHandler timeoutHandler);
void ILibAsyncSocket_SetTimeoutEx(ILibAsyncSocket_SocketModule module, int timeoutMilliseconds, ILibAsyncSocket_TimeoutHandler timeoutHandler);
#define ILibAsyncSocket_SetTimeout(module, timeoutSeconds, timeoutHandler) ILibAsyncSocket_SetTimeoutEx(module, timeoutSeconds*1000, timeoutHandler)
#ifndef MICROSTACK_NOTLS
X509 *ILibAsyncSocket_SslGetCert(ILibAsyncSocket_SocketModule socketModule);

View File

@@ -210,6 +210,7 @@ struct HashNode_Root
{
struct HashNode *Root;
int CaseInSensitive;
void *Reserved;
sem_t LOCK;
};
struct HashNode
@@ -1063,7 +1064,30 @@ typedef struct ILibBaseChain
}ILibBaseChain;
const int ILibMemory_CHAIN_CONTAINERSIZE = sizeof(ILibBaseChain);
void* ILibMemory_AllocateA_InitMem(void *buffer, size_t bufferLen)
{
char *retVal = ((char*)buffer + 8 + sizeof(void*));
((int*)(retVal - 4))[0] = (int)(bufferLen - 8 - sizeof(void*)); // Size
((void**)(retVal - 4 - sizeof(void*)))[0] = retVal; // Next
((int*)buffer)[0] = (int)bufferLen; // RawSize
memset(retVal, 0, bufferLen - 8 - sizeof(void*));
return((void*)retVal);
}
void* ILibMemory_AllocateA_Get(void *buffer, size_t sz)
{
char *retVal = NULL;
if (ILibMemory_AllocateA_Size(buffer) > (int)sz)
{
retVal = ILibMemory_AllocateA_Next(buffer);
ILibMemory_AllocateA_Size(buffer) -= (int)sz;
ILibMemory_AllocateA_Next(buffer) = (char*)ILibMemory_AllocateA_Next(buffer) + (int)sz;
}
return(retVal);
}
void* ILibMemory_Allocate(int containerSize, int extraMemorySize, void** allocatedContainer, void **extraMemory)
{
char* retVal = (char*)malloc(containerSize + extraMemorySize + (extraMemorySize > 0 ? 4 : 0));
@@ -3671,26 +3695,47 @@ void ILibHashTree_GetValueEx(void *tree_enumerator, char **key, int *keyLength,
\brief Creates an empty ILibHashTree, whose keys are <B>case sensitive</B>.
\return An empty ILibHashTree
*/
void* ILibInitHashTree()
void* ILibInitHashTreeEx(void *ReservedMemory)
{
struct HashNode_Root *Root;
struct HashNode *RetVal;
if (ReservedMemory != NULL)
{
if (ILibMemory_AllocateA_Size(ReservedMemory) > sizeof(struct HashNode_Root) + sizeof(struct HashNode))
{
Root = (struct HashNode_Root*)ILibMemory_AllocateA_Get(ReservedMemory, sizeof(struct HashNode_Root));
RetVal = (struct HashNode*)ILibMemory_AllocateA_Get(ReservedMemory, sizeof(struct HashNode));
if (Root == NULL || RetVal == NULL) { ILIBCRITICALEXIT(254); }
memset(RetVal, 0, sizeof(struct HashNode));
memset(Root, 0, sizeof(struct HashNode_Root));
Root->Reserved = ReservedMemory;
}
else
{
return(NULL);
}
}
else
{
if ((Root = (struct HashNode_Root*)malloc(sizeof(struct HashNode_Root))) == NULL) ILIBCRITICALEXIT(254);
if ((RetVal = (struct HashNode*)malloc(sizeof(struct HashNode))) == NULL) ILIBCRITICALEXIT(254);
memset(RetVal, 0, sizeof(struct HashNode));
memset(Root, 0, sizeof(struct HashNode_Root));
}
Root->Root = RetVal;
sem_init(&(Root->LOCK), 0, 1);
if (ReservedMemory == NULL) { sem_init(&(Root->LOCK), 0, 1); }
return(Root);
}
/*! \fn void* ILibInitHashTree_CaseInSensitive()
\brief Creates an empty ILibHashTree, whose keys are <B>case insensitive</B>.
\return An empty ILibHashTree
*/
void* ILibInitHashTree_CaseInSensitive()
void* ILibInitHashTree_CaseInSensitiveEx(void *ReservedMemory)
{
struct HashNode_Root *Root = (struct HashNode_Root*)ILibInitHashTree();
Root->CaseInSensitive = 1;
struct HashNode_Root *Root = (struct HashNode_Root*)ILibInitHashTreeEx(ReservedMemory);
if (Root != NULL) { Root->CaseInSensitive = 1; }
return(Root);
}
@@ -3865,11 +3910,11 @@ struct HashNode* ILibFindEntry(void *hashtree, void *key, int keylength, int cre
//
// If there is no match, and the create flag is set, we need to create an entry
//
if ((current->Next = (struct HashNode*)malloc(sizeof(struct HashNode))) == NULL) ILIBCRITICALEXIT(254);
if ((current->Next = (struct HashNode*)(root->Reserved == NULL ? (malloc(sizeof(struct HashNode))) : ILibMemory_AllocateA_Get(root->Reserved, sizeof(struct HashNode)))) == NULL) ILIBCRITICALEXIT(254);
memset(current->Next,0,sizeof(struct HashNode));
current->Next->Prev = current;
current->Next->KeyHash = HashValue;
if ((current->Next->KeyValue = (void*)malloc(keylength + 1)) == NULL) ILIBCRITICALEXIT(254);
if ((current->Next->KeyValue = (root->Reserved == NULL ? (void*)malloc(keylength + 1) : ILibMemory_AllocateA_Get(root->Reserved, keylength + 1))) == NULL) ILIBCRITICALEXIT(254);
memcpy_s(current->Next->KeyValue, keylength + 1, key ,keylength);
current->Next->KeyValue[keylength] = 0;
current->Next->KeyLength = keylength;
@@ -5171,17 +5216,18 @@ ILibParseUriResult ILibParseUriEx (const char* URI, size_t URILen, char** Addr,
\brief Creates an empty packetheader structure
\return An empty packet
*/
struct packetheader *ILibCreateEmptyPacket()
struct packetheader *ILibCreateEmptyPacketEx(void *ReservedMemory)
{
struct packetheader *RetVal;
if ((RetVal = (struct packetheader*)malloc(sizeof(struct packetheader))) == NULL) ILIBCRITICALEXIT(254);
ILibHTTPPacket *RetVal = ReservedMemory == NULL ? (ILibHTTPPacket*)malloc(sizeof(ILibHTTPPacket)) : (ILibHTTPPacket*)ILibMemory_AllocateA_Get(ReservedMemory, sizeof(ILibHTTPPacket));
if (RetVal == NULL) { ILIBCRITICALEXIT(254); }
memset(RetVal,0,sizeof(struct packetheader));
RetVal->ReservedMemory = ReservedMemory;
RetVal->UserAllocStrings = -1;
RetVal->StatusCode = -1;
RetVal->Version = "1.0";
RetVal->VersionLength = 3;
RetVal->HeaderTable = ILibInitHashTree_CaseInSensitive();
RetVal->HeaderTable = ILibInitHashTree_CaseInSensitiveEx(ReservedMemory);
return RetVal;
}
@@ -5285,16 +5331,32 @@ void ILibSetDirective(struct packetheader *packet, char* Directive, int Directiv
if (DirectiveLength < 0)DirectiveLength = (int)strnlen_s(Directive, 255);
if (DirectiveObjLength < 0)DirectiveObjLength = (int)strnlen_s(DirectiveObj, 255);
if (packet->ReservedMemory != NULL)
{
if (ILibMemory_AllocateA_Size(packet->ReservedMemory) > (DirectiveLength + DirectiveObjLength + 2))
{
packet->Directive = (char*)ILibMemory_AllocateA_Get(packet->ReservedMemory, (size_t)DirectiveLength + 1);
packet->DirectiveObj = (char*)ILibMemory_AllocateA_Get(packet->ReservedMemory, (size_t)DirectiveObjLength + 1);
}
else
{
ILIBCRITICALEXIT(254);
}
}
else
{
if ((packet->Directive = (char*)malloc(DirectiveLength + 1)) == NULL) ILIBCRITICALEXIT(254);
if ((packet->DirectiveObj = (char*)malloc(DirectiveObjLength + 1)) == NULL) ILIBCRITICALEXIT(254);
packet->UserAllocStrings = -1;
}
memcpy_s(packet->Directive, DirectiveLength + 1, Directive,DirectiveLength);
packet->Directive[DirectiveLength] = '\0';
packet->DirectiveLength = DirectiveLength;
if ((packet->DirectiveObj = (char*)malloc(DirectiveObjLength+1)) == NULL) ILIBCRITICALEXIT(254);
memcpy_s(packet->DirectiveObj, DirectiveObjLength + 1, DirectiveObj, DirectiveObjLength);
packet->DirectiveObj[DirectiveObjLength] = '\0';
packet->DirectiveObjLength = DirectiveObjLength;
packet->UserAllocStrings = -1;
}
void ILibHTTPPacket_Stash_Put(ILibHTTPPacket *packet, char* key, int keyLen, void *data)
@@ -5335,25 +5397,40 @@ void ILibAddHeaderLine(struct packetheader *packet, const char* FieldName, int F
struct packetheader_field_node *node;
if (FieldNameLength < 0) { FieldNameLength = (int)strnlen_s(FieldName, 255); }
if (FieldDataLength < 0) { FieldDataLength = (int)strnlen_s(FieldData, 255); }
if (packet->ReservedMemory != NULL)
{
if (ILibMemory_AllocateA_Size(packet->ReservedMemory) > (sizeof(struct packetheader_field_node) + FieldNameLength + FieldDataLength + 2))
{
node = (packetheader_field_node*)ILibMemory_AllocateA_Get(packet->ReservedMemory, sizeof(packetheader_field_node));
node->Field = (char*)ILibMemory_AllocateA_Get(packet->ReservedMemory, (size_t)FieldNameLength + 1);
node->FieldData = (char*)ILibMemory_AllocateA_Get(packet->ReservedMemory, (size_t)FieldDataLength + 1);
}
else
{
return;
}
}
else
{
//
// Create the Header Node
//
if ((node = (struct packetheader_field_node*)malloc(sizeof(struct packetheader_field_node))) == NULL) ILIBCRITICALEXIT(254);
node->UserAllocStrings = -1;
if ((node->Field = (char*)malloc(FieldNameLength + 1)) == NULL) ILIBCRITICALEXIT(254);
if ((node->FieldData = (char*)malloc(FieldDataLength + 1)) == NULL) ILIBCRITICALEXIT(254);
}
memcpy_s(node->Field, FieldNameLength + 1, (char*)FieldName, FieldNameLength);
node->Field[FieldNameLength] = '\0';
node->FieldLength = FieldNameLength;
if ((node->FieldData = (char*)malloc(FieldDataLength+1)) == NULL) ILIBCRITICALEXIT(254);
memcpy_s(node->FieldData, FieldDataLength + 1, (char*)FieldData, FieldDataLength);
node->FieldData[FieldDataLength] = '\0';
node->FieldDataLength = FieldDataLength;
node->NextField = NULL;
ILibAddEntryEx(packet->HeaderTable,node->Field,node->FieldLength,node->FieldData,node->FieldDataLength);
if (packet->HeaderTable != NULL) { ILibAddEntryEx(packet->HeaderTable, node->Field, node->FieldLength, node->FieldData, node->FieldDataLength); }
//
// And attach it to the linked list

View File

@@ -224,7 +224,7 @@ long ILibGetTimeStamp();
#endif
#ifndef strnlen_s
#define strnlen_s(source, maxCount) (strlen(source) < (maxCount) ? strlen(source) : (maxCount))
#define strnlen_s(source, maxCount) (strlen(source) < (maxCount) ? strlen(source) : ((size_t)(maxCount)))
#endif
#ifndef sprintf_s
@@ -233,10 +233,6 @@ long ILibGetTimeStamp();
int sprintf_s(void *dest, size_t destSize, char *format, ...);
#endif
#ifndef strnlen_s
#define strnlen_s(source, maxLen) strnlen(source, maxLen)
#endif
#endif
@@ -305,6 +301,18 @@ int ILibIsRunningOnChainThread(void* chain);
ILibChain_Link* ILibChain_Link_Allocate(int structSize, int extraMemorySize);
int ILibChain_Link_GetExtraMemorySize(ILibChain_Link* link);
#ifdef WIN32
#define ILibMemory_AllocateA(bufferLen) ILibMemory_AllocateA_InitMem(_alloca(8+bufferLen+sizeof(void*)), (size_t)(8+bufferLen+sizeof(void*)))
#else
#define ILibMemory_AllocateA(bufferLen) ILibMemory_AllocateA_InitMem(alloca(8+bufferLen+sizeof(void*)), (size_t)(8+bufferLen+sizeof(void*)))
#endif
#define ILibMemory_AllocateA_Size(buffer) (((int*)((char*)(buffer)-4))[0])
#define ILibMemory_AllocateA_Next(buffer) (((void**)((char*)(buffer)-4-sizeof(void*)))[0])
#define ILibMemory_AllocateA_Raw(buffer) ((void*)((char*)(buffer)-4-sizeof(void*)-4))
#define ILibMemory_AllocateA_RawSize(buffer) (((int*)((char*)(buffer)-4-sizeof(void*)-4))[0])
void* ILibMemory_AllocateA_Get(void *buffer, size_t sz);
void* ILibMemory_AllocateA_InitMem(void *buffer, size_t bufferLen);
void* ILibMemory_Allocate(int containerSize, int extraMemorySize, void** allocatedContainer, void **extraMemory);
int ILibMemory_GetExtraMemorySize(void* extraMemory);
ILibExportMethod void* ILibMemory_GetExtraMemory(void *container, int containerSize);
@@ -534,6 +542,7 @@ int ILibIsRunningOnChainThread(void* chain);
*/
void *Reserved;
char *ReservedMemory;
int DirectiveObjLength;
/*! \var StatusCode
@@ -1049,9 +1058,10 @@ int ILibIsRunningOnChainThread(void* chain);
\b Note: Duplicate key entries will be overwritten.
*@{
*/
void* ILibInitHashTree();
void* ILibInitHashTree_CaseInSensitive();
#define ILibInitHashTree() ILibInitHashTreeEx(NULL)
void* ILibInitHashTreeEx(void *ReservedMemory);
void* ILibInitHashTree_CaseInSensitiveEx(void *ReservedMemory);
#define ILibInitHashTree_CaseInSensitive() ILibInitHashTree_CaseInSensitiveEx(NULL)
void ILibDestroyHashTree(void *tree);
int ILibHasEntry(void *hashtree, char* key, int keylength);
void ILibAddEntry(void* hashtree, char* key, int keylength, void *value);
@@ -1187,7 +1197,8 @@ int ILibIsRunningOnChainThread(void* chain);
/* Packet Methods */
struct packetheader *ILibCreateEmptyPacket();
struct packetheader *ILibCreateEmptyPacketEx(void *ReservedMemory);
#define ILibCreateEmptyPacket() ILibCreateEmptyPacketEx(NULL)
void ILibAddHeaderLine(struct packetheader *packet, const char* FieldName, int FieldNameLength, const char* FieldData, int FieldDataLength);
void ILibDeleteHeaderLine(struct packetheader *packet, char* FieldName, int FieldNameLength);
void ILibHTTPPacket_Stash_Put(ILibHTTPPacket *packet, char* key, int keyLen, void *data);

View File

@@ -109,6 +109,7 @@ typedef struct ILibProcessPipe_Process_Object
ILibProcessPipe_Process_ExitHandler exitHandler;
#ifdef WIN32
HANDLE hProcess;
int hProcess_needAdd;
#endif
void *chain;
}ILibProcessPipe_Process_Object;
@@ -153,6 +154,7 @@ ILibProcessPipe_Pipe ILibProcessPipe_Process_GetStdOut(ILibProcessPipe_Process p
}
#ifdef WIN32
BOOL ILibProcessPipe_Process_OnExit(HANDLE event, void* user);
typedef struct ILibProcessPipe_WaitHandle
{
ILibProcessPipe_Manager_Object *parent;
@@ -203,6 +205,7 @@ void ILibProcessPipe_WaitHandle_AddEx(ILibProcessPipe_Manager mgr, ILibProcessPi
{
// We're on the same thread, so we can just add it in
ILibLinkedList_AddTail(manager->ActivePipes, waitHandle);
SetEvent(manager->updateEvent);
}
else
@@ -222,7 +225,6 @@ void ILibProcessPipe_WaitHandle_Add(ILibProcessPipe_Manager mgr, HANDLE event, v
waitHandle->user = user;
waitHandle->callback = callback;
ILibProcessPipe_WaitHandle_AddEx(mgr, waitHandle);
}
@@ -740,9 +742,9 @@ void ILibProcessPipe_Pipe_SwapBuffers(ILibProcessPipe_Pipe obj, char* newBuffer,
ILibProcessPipe_PipeObject *pipeObject = (ILibProcessPipe_PipeObject*)obj;
*oldBuffer = pipeObject->buffer;
*oldBufferLen = pipeObject->bufferSize;
*oldBufferReadOffset = pipeObject->readOffset;
*oldBufferTotalBytesRead = pipeObject->totalRead;
if (oldBufferLen != NULL) { *oldBufferLen = pipeObject->bufferSize; }
if (oldBufferReadOffset != NULL) { *oldBufferReadOffset = pipeObject->readOffset; }
if (oldBufferTotalBytesRead != NULL) { *oldBufferTotalBytesRead = pipeObject->totalRead; }
pipeObject->buffer = newBuffer;
pipeObject->bufferSize = newBufferLen;
@@ -1129,6 +1131,11 @@ void ILibProcessPipe_Pipe_Resume(ILibProcessPipe_Pipe pipeObject)
else
{
ILibProcessPipe_Pipe_ResumeEx(p);
if (p->mProcess != NULL && p->mProcess->hProcess_needAdd != 0)
{
p->mProcess->hProcess_needAdd = 0;
ILibProcessPipe_WaitHandle_Add(p->manager, p->mProcess->hProcess, p->mProcess, ILibProcessPipe_Process_OnExit);
}
}
#else
ILibProcessPipe_Pipe_ResumeEx(p);
@@ -1231,6 +1238,7 @@ void ILibProcessPipe_Process_PipeHandler_StdIn(void *user1, void *user2)
if (sendOk != NULL) sendOk(j, j->userObject);
}
#ifdef WIN32
void ILibProcessPipe_Process_OnExit_ChainSink(void *chain, void *user)
{
@@ -1241,9 +1249,9 @@ void ILibProcessPipe_Process_OnExit_ChainSink(void *chain, void *user)
result = GetExitCodeProcess(j->hProcess, &exitCode);
j->exiting = 1;
j->exitHandler(j, exitCode, j->userObject);
j->exiting = 0;
j->exiting ^= 1;
ILibProcessPipe_Process_Destroy(j);
if (j->exiting == 0) { ILibProcessPipe_Process_Destroy(j); }
}
BOOL ILibProcessPipe_Process_OnExit(HANDLE event, void* user)
{
@@ -1251,7 +1259,12 @@ BOOL ILibProcessPipe_Process_OnExit(HANDLE event, void* user)
UNREFERENCED_PARAMETER(event);
ILibProcessPipe_WaitHandle_Remove(j->parent, j->hProcess);
if (j->stdOut->PAUSED != 0 || j->stdErr->PAUSED != 0)
{
j->hProcess_needAdd = 1;
}
else
{
if (j->exitHandler != NULL)
{
// Everyone's lifes is made easier, by context switching to chain thread before making this call
@@ -1261,6 +1274,7 @@ BOOL ILibProcessPipe_Process_OnExit(HANDLE event, void* user)
{
ILibProcessPipe_Process_Destroy(j);
}
}
return(FALSE);
}
#endif

View File

@@ -149,6 +149,8 @@ struct ILibWebClient_StreamedRequestState
int done;
int canceled;
int doNotSendRightAway;
int idleTimeout;
ILibAsyncSocket_TimeoutHandler idleTimeoutHandler;
};
struct ILibWebClientManager
@@ -204,9 +206,12 @@ typedef struct ILibWebClientDataObject
int IsOrphan;
int PipelineFlag;
int ActivityCounter;
int NC;
char CNONCE[17];
struct sockaddr_in6 remote;
struct sockaddr_in6 proxy;
struct ILibWebClientManager *Parent;
char* DigestData;
int PendingConnectionIndex;
@@ -248,6 +253,7 @@ typedef struct ILibWebClientDataObject
char CertificateHash[32]; // Used by the Mesh to store NodeID of this session
}ILibWebClientDataObject;
struct ILibWebRequest;
typedef struct ILibWebClient_PipelineRequestToken
{
struct ILibWebClientDataObject *wcdo;
@@ -255,6 +261,7 @@ typedef struct ILibWebClient_PipelineRequestToken
char* WebSocketKey;
int WebSocketMaxBuffer;
ILibWebClient_OnSendOK WebSocketSendOK;
struct ILibWebRequest *parent;
char host[255];
char reserved[29];
}ILibWebClient_PipelineRequestToken;
@@ -277,6 +284,8 @@ typedef struct ILibWebRequest
ILibWebRequest_buffer *buffered;
struct sockaddr_in6 remote;
void *user1,*user2;
ILibWebClient_OnConnectHandler ConnectSink, DisconnectSink;
int connectionCloseWasSpecified;
struct ILibWebClient_PipelineRequestToken *requestToken;
struct ILibWebClient_StreamedRequestState *streamedState;
@@ -332,6 +341,7 @@ void ILibWebClient_DestroyWebRequest(struct ILibWebRequest *wr)
struct ILibWebClient_StreamedRequestBuffer *b;
if (wr == NULL) return;
if (wr != NULL && wr->connectionCloseWasSpecified != 0 && wr->DisconnectSink != NULL) { wr->DisconnectSink(wr->requestToken); }
if (wr->buffered != NULL) { free(wr->buffered); }
if (wr->streamedState != NULL)
{
@@ -455,12 +465,13 @@ void ILibWebClient_DestroyWebClientDataObject(ILibWebClient_StateObject token)
{
free(((ILibWebClient_WebSocketState*)wr->Buffer[0])->WebSocketFragmentBuffer);
}
wr->connectionCloseWasSpecified = 2;
ILibWebClient_DestroyWebRequest(wr);
ILibQueue_DeQueue(wcdo->RequestQueue);
}
ILibQueue_Destroy(wcdo->RequestQueue);
if (wcdo->DigestData != NULL) { free(ILibMemory_AllocateA_Raw(wcdo->DigestData)); }
free(wcdo);
}
@@ -674,7 +685,7 @@ void ILibWebClient_FinishedResponse(ILibAsyncSocket_SocketModule socketModule, s
{
int i;
struct ILibWebRequest *wr;
int closeSpecified = 0;
UNREFERENCED_PARAMETER( socketModule );
if (wcdo == NULL) return;
@@ -718,6 +729,7 @@ void ILibWebClient_FinishedResponse(ILibAsyncSocket_SocketModule socketModule, s
}
// Reset the flags
closeSpecified = wcdo->ConnectionCloseSpecified;
ILibWebClient_ResetWCDO(wcdo);
// If this socket isn't connected, it's because it was previously closed,
@@ -726,7 +738,9 @@ void ILibWebClient_FinishedResponse(ILibAsyncSocket_SocketModule socketModule, s
{
SEM_TRACK(WebClient_TrackLock("ILibWebClient_FinishedResponse", 1, wcdo->Parent);)
sem_wait(&(wcdo->Parent->QLock));
ILibWebClient_DestroyWebRequest((struct ILibWebRequest*)ILibQueue_DeQueue(wcdo->RequestQueue));
wr = (struct ILibWebRequest*)ILibQueue_DeQueue(wcdo->RequestQueue);
wr->connectionCloseWasSpecified = 2;
ILibWebClient_DestroyWebRequest(wr);
SEM_TRACK(WebClient_TrackUnLock("ILibWebClient_FinishedResponse", 2, wcdo->Parent);)
sem_post(&(wcdo->Parent->QLock));
return;
@@ -741,6 +755,7 @@ void ILibWebClient_FinishedResponse(ILibAsyncSocket_SocketModule socketModule, s
// Only execute this logic, if there was a pending request. If there wasn't one, that means
// that this session was closed the last time the app as called with data, making this next step unnecessary.
//
wr->connectionCloseWasSpecified = closeSpecified;
ILibWebClient_DestroyWebRequest(wr);
wr = (struct ILibWebRequest*)ILibQueue_PeekQueue(wcdo->RequestQueue);
if (wr == NULL)
@@ -764,7 +779,7 @@ void ILibWebClient_FinishedResponse(ILibAsyncSocket_SocketModule socketModule, s
//
// There are still pending requests in the queue, so try to send them
//
if (wcdo->PipelineFlag != PIPELINE_NO)
if (wcdo->PipelineFlag != PIPELINE_NO && closeSpecified == 0)
{
ILibWebRequest_buffer *b;
//
@@ -789,7 +804,7 @@ void ILibWebClient_FinishedResponse(ILibAsyncSocket_SocketModule socketModule, s
}
}
}
if (wcdo->PipelineFlag == PIPELINE_NO)
if (wcdo->PipelineFlag == PIPELINE_NO || closeSpecified != 0)
{
//{{{ <--REMOVE_THIS_FOR_HTTP/1.0_ONLY_SUPPORT }}}
/* Pipelining is not supported, so we should just close the socket, instead
@@ -2012,6 +2027,7 @@ void ILibWebClient_OnConnect(ILibAsyncSocket_SocketModule socketModule, int Conn
//printf("ILibWebClient_OnConnect(). Connected=%d, DisconnectSent=%d\r\n", Connected, wcdo->DisconnectSent);
if (wcdo->Closing != 0) return; // Already closing, exit now
wcdo->SOCK = socketModule;
@@ -2031,6 +2047,7 @@ void ILibWebClient_OnConnect(ILibAsyncSocket_SocketModule socketModule, int Conn
sem_post(&(wcdo->Parent->QLock));
if (r != NULL)
{
if (r->ConnectSink != NULL) { r->ConnectSink(r->requestToken); }
ILibWebRequest_buffer *b;
for(i = 0; i < r->NumberOfBuffers; ++i)
{
@@ -2044,7 +2061,11 @@ void ILibWebClient_OnConnect(ILibAsyncSocket_SocketModule socketModule, int Conn
r->buffered = r->buffered->next;
free(b);
}
if (r->streamedState != NULL) ILibWebClient_OnSendOKSink(socketModule, wcdo);
if (r->streamedState != NULL)
{
if (r->streamedState->idleTimeout > 0 && r->streamedState->idleTimeoutHandler != NULL) { ILibAsyncSocket_SetTimeoutEx(socketModule, r->streamedState->idleTimeout, r->streamedState->idleTimeoutHandler); }
ILibWebClient_OnSendOKSink(socketModule, wcdo);
}
}
}
else
@@ -2162,7 +2183,8 @@ void ILibWebClient_OnDisconnectSink(ILibAsyncSocket_SocketModule socketModule, v
}
ILibWebClient_ResetWCDO(wcdo);
if (wcdo->DisconnectSent == 1) wcdo->DisconnectSent = 0;
if (wr != NULL) ILibWebClient_DestroyWebRequest(wr);
if (wr != NULL && wr->DisconnectSink != NULL) { wr->DisconnectSink(wr->requestToken); }
if (wr != NULL) { wr->connectionCloseWasSpecified = 3; ILibWebClient_DestroyWebRequest(wr); }
if (h != NULL) ILibDestructPacket(h);
}
@@ -2209,6 +2231,7 @@ void ILibWebClient_OnDisconnectSink(ILibAsyncSocket_SocketModule socketModule, v
{
free(((ILibWebClient_WebSocketState*)wr->Buffer[0])->WebSocketFragmentBuffer);
}
wr->connectionCloseWasSpecified = 2;
ILibWebClient_DestroyWebRequest(wr);
}
}
@@ -2634,7 +2657,7 @@ ILibWebClient_RequestToken ILibWebClient_PipelineRequestEx2(
request->UserFree[0] = headerBuffer_FREE;
ILibMemory_Allocate(sizeof(ILibWebClient_PipelineRequestToken), 32, (void**)&(request->requestToken), NULL);
request->requestToken->parent = request;
request->requestToken->timer = wcm->timer;
if (headerBufferLength > 5 && strncasecmp("HEAD ", headerBuffer, 5) == 0)
@@ -2727,11 +2750,9 @@ ILibWebClient_RequestToken ILibWebClient_PipelineRequestEx2(
RequestTokenLength = ILibCreateTokenStr(RemoteEndpoint, 0, RequestToken);
}
if (ILibHasEntry(wcm->DataTable, RequestToken, RequestTokenLength)!=0)
if ((wcdo = (struct ILibWebClientDataObject*)ILibGetEntry(wcm->DataTable, RequestToken, RequestTokenLength)) != NULL)
{
// Yes it does!
wcdo = (struct ILibWebClientDataObject*)ILibGetEntry(wcm->DataTable, RequestToken, RequestTokenLength);
if (wcdo == NULL) ILIBCRITICALEXIT(253); // TODO: Better handling....
// Previous connection exists!
request->requestToken->wcdo = wcdo;
if (ILibQueue_IsEmpty(wcdo->RequestQueue) != 0)
{
@@ -2761,6 +2782,7 @@ ILibWebClient_RequestToken ILibWebClient_PipelineRequestEx2(
}
if (request->streamedState != NULL)
{
if (request->streamedState->idleTimeout > 0 && request->streamedState->idleTimeoutHandler != NULL) { ILibAsyncSocket_SetTimeoutEx(wcdo->SOCK, request->streamedState->idleTimeout, request->streamedState->idleTimeoutHandler); }
ILibWebClient_OnSendOKSink(wcdo->SOCK, wcdo);
}
}
@@ -3162,22 +3184,8 @@ ILibWebClient_RequestToken ILibWebClient_GetRequestToken_FromStateObject(ILibWeb
void **ILibWebClient_RequestToken_GetUserObjects(ILibWebClient_RequestToken tok)
{
struct ILibWebClientDataObject *wcdo = (struct ILibWebClientDataObject*)ILibWebClient_GetStateObjectFromRequestToken(tok);
struct ILibWebRequest *wr;
if (wcdo == NULL) return(NULL);
wr = (struct ILibWebRequest*)ILibQueue_PeekQueue(wcdo->RequestQueue);
if (wr != NULL) { return(&(wr->user1)); } else { return(NULL); }
}
void **ILibWebClient_RequestToken_GetUserObjects_Tail(ILibWebClient_RequestToken tok)
{
struct ILibWebClientDataObject *wcdo = (struct ILibWebClientDataObject*)ILibWebClient_GetStateObjectFromRequestToken(tok);
struct ILibWebRequest *wr;
if (wcdo == NULL) return(NULL);
wr = (struct ILibWebRequest*)ILibQueue_PeekTail(wcdo->RequestQueue);
if (wr != NULL) { return(&(wr->user1)); }
else { return(NULL); }
ILibWebClient_PipelineRequestToken *prt = (ILibWebClient_PipelineRequestToken*)tok;
return(prt->parent != NULL ? &(prt->parent->user1) : NULL);
}
/*! \fn ILibWebClient_StateObject ILibWebClient_GetStateObjectFromRequestToken(ILibWebClient_RequestToken token)
@@ -3210,6 +3218,13 @@ ILibWebClient_RequestToken ILibWebClient_PipelineStreamedRequest(ILibWebClient_R
state->BufferQueue = ILibQueue_Create();
state->OnSendOK = OnSendOK;
state->doNotSendRightAway = 1;
if (ILibHTTPPacket_Stash_HasKey(packet, "_idleTimeout", 12) != 0)
{
union { int i; void*p; }u;
u.p = ILibHTTPPacket_Stash_Get(packet, "_idleTimeout", 12);
state->idleTimeout = u.i;
state->idleTimeoutHandler = (ILibAsyncSocket_TimeoutHandler)ILibHTTPPacket_Stash_Get(packet, "_idleTimeoutHandler", 19);
}
ILibAddHeaderLine(packet,"Transfer-Encoding",17,"chunked",7);
@@ -3662,14 +3677,27 @@ int ILibWebClient_Digest_NeedAuthenticate(ILibWebClient_StateObject state)
char* authenticate = ILibGetHeaderLine(wcdo->header, "WWW-Authenticate", 16);
return(wcdo->header->StatusCode == 401 && authenticate != NULL);
}
void* ILibWebClient_Digest_GenerateTable(ILibWebClient_StateObject state)
void* ILibWebClient_Digest_GenerateTableEx(ILibWebClient_StateObject state, void *ReservedMemory)
{
ILibWebClientDataObject *wcdo = (ILibWebClientDataObject*)state;
char* authenticate = ILibGetHeaderLineSP(((ILibWebClientDataObject*)state)->header, "WWW-Authenticate", 16);
void* table = ILibInitHashTree_CaseInSensitive();
if (wcdo->DigestData == NULL) { wcdo->DigestData = ILibMemory_AllocateA_InitMem(ILibMemory_Allocate(1024, 0, NULL, NULL), 1024); }
if (authenticate != NULL)
{
ILibMemory_AllocateA_InitMem(ILibMemory_AllocateA_Raw(wcdo->DigestData), ILibMemory_AllocateA_RawSize(wcdo->DigestData));
strncpy_s(wcdo->DigestData, ILibMemory_AllocateA_Size(wcdo->DigestData), authenticate, strnlen_s(authenticate, sizeof(ILibScratchPad)));
}
else
{
authenticate = wcdo->DigestData;
}
void* table = ILibInitHashTree_CaseInSensitiveEx(ReservedMemory);
ILibWebServer_Digest_ParseAuthenticationHeader(table, authenticate, (int)strnlen_s(authenticate, sizeof(ILibScratchPad) - sizeof(void*)));
return(table);
}
#define ILibWebClient_Digest_GenerateTable(state) ILibWebClient_Digest_GenerateTableEx(state, NULL)
char* ILibWebClient_Digest_GetRealm(ILibWebClient_StateObject state)
{
void* table = ILibWebClient_Digest_GenerateTable(state);
@@ -3681,15 +3709,18 @@ char* ILibWebClient_Digest_GetRealm(ILibWebClient_StateObject state)
void ILibWebClient_GenerateAuthenticationHeader(ILibWebClient_StateObject state, ILibHTTPPacket *packet, char* username, char* password)
{
ILibWebClientDataObject *wcdo = (ILibWebClientDataObject*)state;
int tmpLen;
char result1[33];
char result2[33];
char result3[33];
void* table = ILibWebClient_Digest_GenerateTable(state);
void *ReservedMemory = packet->ReservedMemory == NULL ? ILibMemory_AllocateA(8000) : packet->ReservedMemory;
void* table = ILibWebClient_Digest_GenerateTableEx(state, ReservedMemory);
char* realm = (char*)ILibGetEntry(table, "realm", 5);
char* nonce = (char*)ILibGetEntry(table, "nonce", 5);
char* opaque = (char*)ILibGetEntry(table, "opaque", 6);
ILibDestroyHashTree(table);
char *qop = (char*)ILibGetEntry(table, "qop", 3);
tmpLen = sprintf_s(ILibScratchPad2, sizeof(ILibScratchPad2), "%s:%s:%s", username, realm, password);
util_md5hex(ILibScratchPad2, tmpLen, result1);
@@ -3699,10 +3730,30 @@ void ILibWebClient_GenerateAuthenticationHeader(ILibWebClient_StateObject state,
tmpLen = sprintf_s(ILibScratchPad2, sizeof(ILibScratchPad2), "%s:%s", packet->Directive, packet->DirectiveObj);
util_md5hex(ILibScratchPad2, tmpLen, result2);
if (qop == NULL)
{
tmpLen = sprintf_s(ILibScratchPad2, sizeof(ILibScratchPad2), "%s:%s:%s", result1, nonce, result2);
}
else
{
if (wcdo->NC == 0)
{
util_randomtext(sizeof(wcdo->CNONCE)-1, wcdo->CNONCE);
wcdo->CNONCE[sizeof(wcdo->CNONCE) - 1] = 0;
}
wcdo->NC++;
tmpLen = sprintf_s(ILibScratchPad2, sizeof(ILibScratchPad2), "%s:%s:%08x:%s:%s:%s", result1, nonce, wcdo->NC, wcdo->CNONCE, qop, result2);
}
util_md5hex(ILibScratchPad2, tmpLen, result3);
tmpLen = sprintf_s(ILibScratchPad2, sizeof(ILibScratchPad2), "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", opaque=\"%s\", response=\"%s\"", username, realm, nonce, packet->DirectiveObj, opaque, result3);
tmpLen = sprintf_s(ILibScratchPad2, sizeof(ILibScratchPad2), "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\"", username, realm, nonce, packet->DirectiveObj);
if (opaque != NULL) { tmpLen += sprintf_s(ILibScratchPad2 + tmpLen, sizeof(ILibScratchPad2) - tmpLen, ", opaque=\"%s\"", opaque); }
if (qop != NULL)
{
tmpLen += sprintf_s(ILibScratchPad2 + tmpLen, sizeof(ILibScratchPad2) - tmpLen, ", qop=\"%s\", nc=%08x, cnonce=\"%s\"", qop, wcdo->NC, wcdo->CNONCE);
}
tmpLen += sprintf_s(ILibScratchPad2 + tmpLen, sizeof(ILibScratchPad2) - tmpLen, ", response=\"%s\"", result3);
ILibAddHeaderLine(packet, "Authorization", 13, ILibScratchPad2, tmpLen);
}
void ILibWebClient_AddWebSocketRequestHeaders(ILibHTTPPacket *packet, int FragmentReassemblyMaxBufferSize, ILibWebClient_OnSendOK OnSendOK)
@@ -3725,6 +3776,23 @@ void ILibWebClient_AddWebSocketRequestHeaders(ILibHTTPPacket *packet, int Fragme
ILibHTTPPacket_Stash_Put(packet, "_WebSocketBufferSize", 20, u.p);
ILibHTTPPacket_Stash_Put(packet, "_WebSocketOnSendOK", 18, OnSendOK);
}
void ILibWebClient_RequestToken_ConnectionHandler_Set(ILibWebClient_RequestToken token, ILibWebClient_OnConnectHandler OnConnect, ILibWebClient_OnConnectHandler OnDisconnect)
{
ILibWebClientDataObject *wcdo = ILibWebClient_GetStateObjectFromRequestToken(token);
struct ILibWebRequest *wr;
if (wcdo != NULL)
{
sem_wait(&(wcdo->Parent->QLock));
wr = (struct ILibWebRequest*)ILibQueue_PeekTail(wcdo->RequestQueue);
if (wr != NULL)
{
wr->ConnectSink = OnConnect;
wr->DisconnectSink = OnDisconnect;
}
sem_post(&(wcdo->Parent->QLock));
}
}
#ifdef MICROSTACK_PROXY
struct sockaddr_in6* ILibWebClient_SetProxy(ILibWebClient_RequestToken token, char *proxyHost, unsigned short proxyPort, char *username, char *password)
{

View File

@@ -133,6 +133,7 @@ typedef void(*ILibWebClient_OnResponse)(ILibWebClient_StateObject WebStateObject
\param user2 User2 object that was associated with this connection
*/
typedef void(*ILibWebClient_OnSendOK)(ILibWebClient_StateObject sender, void *user1, void *user2);
typedef void(*ILibWebClient_OnConnectHandler)(ILibWebClient_RequestToken sender);
/*! \typedef ILibWebClient_OnDisconnect
\brief Handler for when the session has disconnected
\param sender The \a ILibWebClient_StateObject that has been disconnected
@@ -241,7 +242,8 @@ void ILibWebClient_ResetUserObjects(ILibWebClient_StateObject webstate, void *us
ILibWebClient_RequestToken ILibWebClient_GetRequestToken_FromStateObject(ILibWebClient_StateObject WebStateObject);
ILibWebClient_StateObject ILibWebClient_GetStateObjectFromRequestToken(ILibWebClient_RequestToken token);
void **ILibWebClient_RequestToken_GetUserObjects(ILibWebClient_RequestToken tok);
void **ILibWebClient_RequestToken_GetUserObjects_Tail(ILibWebClient_RequestToken tok);
void ILibWebClient_RequestToken_ConnectionHandler_Set(ILibWebClient_RequestToken tok, ILibWebClient_OnConnectHandler OnConnect, ILibWebClient_OnConnectHandler OnDisconnect);
void ILibWebClient_Parse_ContentRange(char *contentRange, int *Start, int *End, int *TotalLength);
enum ILibWebClient_Range_Result ILibWebClient_Parse_Range(char *Range, long *Start, long *Length, long TotalLength);

View File

@@ -1910,7 +1910,10 @@ int ILibWebServer_GetLocalInterface(struct ILibWebServer_Session *session, struc
return ILibAsyncSocket_GetLocalInterface(ILibWebServer_Session_GetSystemData(session)->ConnectionToken, localAddress);
}
ILibAsyncServerSocket_ServerModule ILibWebServer_GetServerSocketModule(ILibWebServer_ServerToken server)
{
return(((ILibWebServer_StateModule*)server)->ServerSocket);
}
/*! \fn ILibWebServer_RegisterVirtualDirectory(ILibWebServer_ServerToken WebServerToken, char *vd, int vdLength, ILibWebServer_VirtualDirectory OnVirtualDirectory, void *user)
\brief Registers a Virtual Directory with the ILibWebServer

View File

@@ -197,6 +197,7 @@ ILibWebServer_ServerToken ILibWebServer_CreateEx(void *Chain, int MaxConnections
ILibExportMethod ILibWebServer_ServerToken ILibWebServer_CreateEx2(void *Chain, int MaxConnections, unsigned short PortNumber, int loopbackFlag, ILibWebServer_Session_OnSession OnSession, int ExtraMemorySize, void *User);
#define ILibWebServer_Create(Chain, MaxConnections, PortNumber, OnSession, User) ILibWebServer_CreateEx(Chain, MaxConnections, PortNumber, INADDR_ANY, OnSession, User)
#define ILibWebServer_Create2(Chain, MaxConnections, PortNumber, OnSession, ExtraMemorySize, User) ILibWebServer_CreateEx2(Chain, MaxConnections, PortNumber, INADDR_ANY, OnSession, ExtraMemorySize, User)
ILibAsyncServerSocket_ServerModule ILibWebServer_GetServerSocketModule(ILibWebServer_ServerToken server);
void ILibWebServer_StopListener(ILibWebServer_ServerToken server);
void ILibWebServer_RestartListener(ILibWebServer_ServerToken server);