diff --git a/meshcore/agentcore.c b/meshcore/agentcore.c index fbf1bdc..34c0edd 100644 --- a/meshcore/agentcore.c +++ b/meshcore/agentcore.c @@ -108,6 +108,7 @@ int ILibDuktape_HECI_Debug = 0; extern int ILibDuktape_ModSearch_ShowNames; char* MeshAgentHost_BatteryInfo_STRINGS[] = { "UNKNOWN", "HIGH_CHARGE", "LOW_CHARGE", "NO_BATTERY", "CRITICAL_CHARGE", "", "", "", "CHARGING" }; JS_ENGINE_CONTEXT MeshAgent_JavaCore_ContextGuid = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; +extern int ILibInflate(char *buffer, size_t bufferLen, char *decompressed, size_t *decompressedLen, uint32_t crc); typedef struct RemoteDesktop_Ptrs { @@ -2800,10 +2801,13 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge // Process Core Module Commands here, but only if we aren't running a local script switch (command) { + case MeshCommand_CompressedCoreModule: case MeshCommand_CoreModule: // New core modules to be used instead of the old one, if empty, remove the core module { char *coreException = NULL; MeshCommand_BinaryPacket_CoreModule *cm = (MeshCommand_BinaryPacket_CoreModule*)cmd; + char *coremodule = cm->coreModule; + size_t coremoduleLen = (size_t)cmdLen - sizeof(MeshCommand_BinaryPacket_CoreModule); // If the agent is running with a local core, ignore this command if (agent->localScript != 0) break; @@ -2814,10 +2818,35 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge if (hashref == NULL || memcmp(hashref, cm->coreModuleHash, sizeof(cm->coreModuleHash)) != 0) { agent->coreTimeout = NULL; // Setting this to null becuase we're going to stop the core. If we stop the core, this timeout will cleanup by itself. + if (command == MeshCommand_CompressedCoreModule) + { + // meshcore is DEFLATE'ed, so we need to INFLATE it + size_t decompressedModuleLen = 0; + char *decompressedModule = NULL; + if (ILibInflate(coremodule, coremoduleLen, NULL, &decompressedModuleLen, 0) == 0) + { + decompressedModule = (char*)ILibMemory_AllocateTemp(agent->chain, decompressedModuleLen); + if (ILibInflate(coremodule, coremoduleLen, decompressedModule, &decompressedModuleLen, 0) == 0) + { + coremodule = decompressedModule; + coremoduleLen = decompressedModuleLen; + } + else + { + decompressedModule = NULL; + } + } + if (decompressedModule == NULL) + { + ILibRemoteLogging_printf(ILibChainGetLogger(agent->chain), ILibRemoteLogging_Modules_Microstack_Generic | ILibRemoteLogging_Modules_ConsolePrint, + ILibRemoteLogging_Flags_VerbosityLevel_1, "MeshCore: INFLATE error"); + break; + } + } // If server sends us the same core, just do nothing. // Server sent us a new core, start by storing it in the data store - ILibSimpleDataStore_PutCompressed(agent->masterDb, "CoreModule", 10, cm->coreModule, cmdLen - sizeof(MeshCommand_BinaryPacket_CoreModule)); // Store the JavaScript in the data store + ILibSimpleDataStore_PutCompressed(agent->masterDb, "CoreModule", 10, coremodule, (int)coremoduleLen); // Store the JavaScript in the data store hashref = ILibSimpleDataStore_GetHash(agent->masterDb, "CoreModule"); // Get the reference to the SHA384 hash if (memcmp(hashref, cm->coreModuleHash, sizeof(cm->coreModuleHash)) != 0) { // Check the hash for sanity @@ -2842,7 +2871,7 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge //printf("CORE: Restart\r\n"); ILibRemoteLogging_printf(ILibChainGetLogger(agent->chain), ILibRemoteLogging_Modules_Microstack_Generic | ILibRemoteLogging_Modules_ConsolePrint, ILibRemoteLogging_Flags_VerbosityLevel_1, "MeshCore: Restart"); - if ((coreException = ScriptEngine_Restart(agent, MeshAgent_JavaCore_ContextGuid, cm->coreModule + 4, cmdLen - sizeof(MeshCommand_BinaryPacket_CoreModule) - 4)) != NULL) + if ((coreException = ScriptEngine_Restart(agent, MeshAgent_JavaCore_ContextGuid, coremodule + 4, (int)coremoduleLen - 4)) != NULL) { ILibRemoteLogging_printf(ILibChainGetLogger(agent->chain), ILibRemoteLogging_Modules_Microstack_Generic | ILibRemoteLogging_Modules_ConsolePrint, ILibRemoteLogging_Flags_VerbosityLevel_1, "MeshCore: Error: %s", coreException); @@ -3826,7 +3855,7 @@ MeshAgentHostContainer* MeshAgent_Create(MeshCommand_AuthInfo_CapabilitiesMask c retVal->agentID = (AgentIdentifiers)MESH_AGENTID; retVal->chain = ILibCreateChainEx(3 * sizeof(void*)); retVal->pipeManager = ILibProcessPipe_Manager_Create(retVal->chain); - retVal->capabilities = capabilities | MeshCommand_AuthInfo_CapabilitiesMask_CONSOLE | MeshCommand_AuthInfo_CapabilitiesMask_JAVASCRIPT; + retVal->capabilities = capabilities | MeshCommand_AuthInfo_CapabilitiesMask_CONSOLE | MeshCommand_AuthInfo_CapabilitiesMask_JAVASCRIPT | MeshCommand_AuthInfo_CapabilitiesMask_COMPRESSION; #ifdef WIN32 diff --git a/meshcore/agentcore.h b/meshcore/agentcore.h index cfa93b3..b883447 100644 --- a/meshcore/agentcore.h +++ b/meshcore/agentcore.h @@ -110,6 +110,7 @@ typedef enum MeshCommands_Binary 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_CompressedCoreModule = 20, MeshCommand_CoreModuleHash = 11, // Request/return the SHA384 hash of the core module MeshCommand_AgentHash = 12, // Request/return the SHA384 hash of the agent executable MeshCommand_AgentUpdate = 13, // Indicate the start and end of the mesh agent binary transfer diff --git a/microscript/ILibDuktape_HttpStream.c b/microscript/ILibDuktape_HttpStream.c index 615d1da..ac837fe 100644 --- a/microscript/ILibDuktape_HttpStream.c +++ b/microscript/ILibDuktape_HttpStream.c @@ -464,44 +464,48 @@ duk_ret_t ILibDuktape_HttpStream_http_onUpgrade(duk_context *ctx) duk_get_prop_string(ctx, 0, "headers"); // [headers] duk_get_prop_string(ctx, -1, "Sec-WebSocket-Accept"); // [headers][key] key = (char*)Duktape_GetBuffer(ctx, -1, &keyLen); - duk_get_prop_string(ctx, -2, "Sec-WebSocket-Extensions"); // [headers][key][extensions] - duk_string_split(ctx, -1, ";"); // [headers][key][extensions][array] - while (duk_get_length(ctx, -1) > 0) + + if (duk_has_prop_string(ctx, -2, "Sec-WebSocket-Extensions")) { - duk_array_pop(ctx, -1); // [headers][key][extensions][array][string] - duk_string_split(ctx, -1, "="); // [headers][key][extensions][array][string][array] - duk_array_shift(ctx, -1); // [headers][key][extensions][array][string][array][val1] - if (strcmp("permessage-deflate", duk_to_string(ctx, -1)) == 0) { permessageDeflate = 1; duk_pop_3(ctx); } - else if (strcmp("server_max_window_bits", duk_to_string(ctx, -1)) == 0) + duk_get_prop_string(ctx, -2, "Sec-WebSocket-Extensions"); // [headers][key][extensions] + duk_string_split(ctx, -1, ";"); // [headers][key][extensions][array] + while (duk_get_length(ctx, -1) > 0) { - if (duk_get_length(ctx, -2) > 0) + duk_array_pop(ctx, -1); // [headers][key][extensions][array][string] + duk_string_split(ctx, -1, "="); // [headers][key][extensions][array][string][array] + duk_array_shift(ctx, -1); // [headers][key][extensions][array][string][array][val1] + if (strcmp("permessage-deflate", duk_to_string(ctx, -1)) == 0) { permessageDeflate = 1; duk_pop_3(ctx); } + else if (strcmp("server_max_window_bits", duk_to_string(ctx, -1)) == 0) { - duk_array_shift(ctx, -2); // [headers][key][extensions][array][string][array][val1][val2] - smwb = duk_to_int(ctx, -1); - duk_pop_n(ctx, 4); // [headers][key][extensions][array] + if (duk_get_length(ctx, -2) > 0) + { + duk_array_shift(ctx, -2); // [headers][key][extensions][array][string][array][val1][val2] + smwb = duk_to_int(ctx, -1); + duk_pop_n(ctx, 4); // [headers][key][extensions][array] + } + else + { + duk_pop_3(ctx); // [headers][key][extensions][array] + } + } + else if (strcmp("client_max_window_bits", duk_to_string(ctx, -1)) == 0) + { + if (duk_get_length(ctx, -2) > 0) + { + duk_array_shift(ctx, -2); // [headers][key][extensions][array][string][array][val1][val2] + cmwb = duk_to_int(ctx, -1); + duk_pop_n(ctx, 4); // [headers][key][extensions][array] + } + else + { + duk_pop_3(ctx); // [headers][key][extensions][array] + } } else { - duk_pop_3(ctx); // [headers][key][extensions][array] + duk_pop_3(ctx); // [headers][key][extensions][array] } } - else if (strcmp("client_max_window_bits", duk_to_string(ctx, -1)) == 0) - { - if (duk_get_length(ctx, -2) > 0) - { - duk_array_shift(ctx, -2); // [headers][key][extensions][array][string][array][val1][val2] - cmwb = duk_to_int(ctx, -1); - duk_pop_n(ctx, 4); // [headers][key][extensions][array] - } - else - { - duk_pop_3(ctx); // [headers][key][extensions][array] - } - } - else - { - duk_pop_3(ctx); // [headers][key][extensions][array] - } } decodedKey = ILibMemory_AllocateA(keyLen);