diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ece2dcc..933ba1f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.13) -project(owgw VERSION 3.2.0) +project(owgw VERSION 3.2.1) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED True) diff --git a/PROTOCOL.md b/PROTOCOL.md index a3af296d..1e14dda6 100644 --- a/PROTOCOL.md +++ b/PROTOCOL.md @@ -324,6 +324,20 @@ should respond with message indicating failure or success. } ``` +If AP supports compressed configuration feature by inidcating `compress_cmd=true` in its capabilities, controller +will send a compressed configuration message where configuration payload (i.e. contents of `params`) is compressed +and encoded in base64 format: +```json +{ "jsonrpc" : "2.0", + "method" : "configure", + "params" : { + "compress_64" : "", + "compress_sz" : "" + }, + "id" : +} +``` + The device should answer: ```json { "jsonrpc" : "2.0", diff --git a/src/RESTAPI/RESTAPI_RPC.cpp b/src/RESTAPI/RESTAPI_RPC.cpp index d7bba1e3..7911da03 100644 --- a/src/RESTAPI/RESTAPI_RPC.cpp +++ b/src/RESTAPI/RESTAPI_RPC.cpp @@ -54,8 +54,8 @@ namespace OpenWifi::RESTAPI_RPC { std::chrono::milliseconds WaitTimeInMs, Poco::JSON::Object *ObjectToReturn, RESTAPIHandler *Handler, Poco::Logger &Logger, bool Deferred) { - Logger.information(fmt::format("{},{}: New {} command. User={} Serial={}. ", Cmd.UUID, - RPCID, Cmd.Command, Cmd.SubmittedBy, Cmd.SerialNumber)); + Logger.information(fmt::format("{},{}: New {} command. User={} Serial={} Details={}. ", Cmd.UUID, + RPCID, Cmd.Command, Cmd.SubmittedBy, Cmd.SerialNumber, Cmd.Details)); Cmd.Submitted = Utils::Now(); Cmd.Executed = 0; diff --git a/src/RESTAPI/RESTAPI_device_commandHandler.cpp b/src/RESTAPI/RESTAPI_device_commandHandler.cpp index 6d0ef9d3..6d1580a0 100644 --- a/src/RESTAPI/RESTAPI_device_commandHandler.cpp +++ b/src/RESTAPI/RESTAPI_device_commandHandler.cpp @@ -694,9 +694,31 @@ namespace OpenWifi { Params.stringify(ParamStream); Cmd.Details = ParamStream.str(); + // retrieve capabilities and encode/compress parameters, if required + Poco::JSON::Object ConfigParams = Params; + GWObjects::Capabilities Caps; + if (StorageService()->GetDeviceCapabilities(SerialNumber_, Caps)) { + Poco::JSON::Object CapsJson; + Caps.to_json(CapsJson); + auto DeviceCaps = CapsJson.getObject(uCentralProtocol::CAPABILITIES); + if (DeviceCaps->has("compress_cmd") && DeviceCaps->get("compress_cmd")) { + // compressed command capability present and it is set, compress parameters + Poco::JSON::Object CompressedParams; + std::string CompressedBase64Data; + std::uint64_t UncompressedDataLen = ParamStream.str().length(); + if (Utils::CompressAndEncodeBase64(ParamStream.str(), CompressedBase64Data)) { + // set compressed, base 64 encoded data and length of uncompressed data + CompressedParams.set(uCentralProtocol::COMPRESS_64, CompressedBase64Data); + CompressedParams.set(uCentralProtocol::COMPRESS_SZ, UncompressedDataLen); + ConfigParams = CompressedParams; + } + } + } + + // AP_WS_Server()->SetPendingUUID(SerialNumber_, NewUUID); RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::configure, true, - Cmd, Params, *Request, *Response, timeout, + Cmd, ConfigParams, *Request, *Response, timeout, nullptr, this, Logger_); if(!Cmd.Executed) { diff --git a/src/framework/ConfigurationValidator.cpp b/src/framework/ConfigurationValidator.cpp index 807d416c..4391d879 100644 --- a/src/framework/ConfigurationValidator.cpp +++ b/src/framework/ConfigurationValidator.cpp @@ -376,18 +376,21 @@ static std::string DefaultAPSchema = R"foo( "properties": { "port-mirror": { "description": "Enable mirror of traffic from multiple minotor ports to a single analysis port.", - "type": "object", - "properties": { - "monitor-ports": { - "description": "The list of ports that we want to mirror.", - "type": "array", - "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "monitor-ports": { + "description": "The list of ports that we want to mirror.", + "type": "array", + "items": { + "type": "string" + } + }, + "analysis-port": { + "description": "The port that mirror'ed packets should be sent to.", "type": "string" } - }, - "analysis-port": { - "description": "The port that mirror'ed packets should be sent to.", - "type": "string" } } }, @@ -4652,16 +4655,22 @@ static std::string DefaultSWITCHSchema = R"foo( "type": "object", "properties": { "port-mirror": { - "type": "object", - "properties": { - "monitor-ports": { - "type": "array", - "items": { + "description": "Enable mirror of traffic from multiple minotor ports to a single analysis port.", + "type": "array", + "items": { + "type": "object", + "properties": { + "monitor-ports": { + "description": "The list of ports that we want to mirror.", + "type": "array", + "items": { + "type": "string" + } + }, + "analysis-port": { + "description": "The port that mirror'ed packets should be sent to.", "type": "string" } - }, - "analysis-port": { - "type": "string" } } }, diff --git a/src/framework/ow_constants.h b/src/framework/ow_constants.h index adac0cc6..0a617e55 100644 --- a/src/framework/ow_constants.h +++ b/src/framework/ow_constants.h @@ -611,6 +611,7 @@ namespace OpenWifi::uCentralProtocol { static const char *CFGPENDING = "cfgpending"; static const char *RECOVERY = "recovery"; static const char *COMPRESS_64 = "compress_64"; + static const char *COMPRESS_SZ = "compress_sz"; static const char *CAPABILITIES = "capabilities"; static const char *REQUEST_UUID = "request_uuid"; static const char *SANITY = "sanity"; diff --git a/src/framework/utils.cpp b/src/framework/utils.cpp index f526e796..4b1cb865 100644 --- a/src/framework/utils.cpp +++ b/src/framework/utils.cpp @@ -590,6 +590,26 @@ namespace OpenWifi::Utils { return false; } + // + // Compress given data using utility function and encode it in base64 format. + // + bool CompressAndEncodeBase64(const std::string& UnCompressedData, std::string& CompressedBase64Data) { + + unsigned long CompressedDataSize = UnCompressedData.size(); + std::vector CompressedData(CompressedDataSize); + auto status = compress(&CompressedData[0], &CompressedDataSize, + (Bytef*) UnCompressedData.c_str(), UnCompressedData.size()); + if (status == Z_OK) { + CompressedBase64Data = OpenWifi::Utils::base64encode(&CompressedData[0], CompressedDataSize); + } + else { + // failed to compress data + return false; + } + + return true; + } + bool IsAlphaNumeric(const std::string &s) { return std::all_of(s.begin(), s.end(), [](char c) -> bool { return isalnum(c); }); } diff --git a/src/framework/utils.h b/src/framework/utils.h index b20d32af..9ebe138c 100644 --- a/src/framework/utils.h +++ b/src/framework/utils.h @@ -151,6 +151,8 @@ namespace OpenWifi::Utils { bool ExtractBase64CompressedData(const std::string &CompressedData, std::string &UnCompressedData, uint64_t compress_sz); + bool CompressAndEncodeBase64(const std::string& UnCompressedData, std::string& CompressedData); + inline bool match(const char* first, const char* second) { // If we reach at the end of both strings, we are done diff --git a/src/storage/storage_command.cpp b/src/storage/storage_command.cpp index 3f8d497c..90b16456 100644 --- a/src/storage/storage_command.cpp +++ b/src/storage/storage_command.cpp @@ -644,8 +644,6 @@ namespace OpenWifi { uint64_t Size = FileContent.str().size(); Poco::Data::Session Sess = Pool_->get(); - Sess.begin(); - Poco::Data::Statement Statement(Sess); if (Size < FileUploader()->MaxSize()) { @@ -668,9 +666,10 @@ namespace OpenWifi { } else { poco_warning(Logger(), fmt::format("File {} is too large.", UUID)); } - Sess.commit(); // update CommandList here to ensure that file us uploaded + Sess.begin(); + Poco::Data::Statement Statement(Sess); std::string StatementStr; StatementStr = "UPDATE CommandList SET WaitingForFile=?, AttachDate=?, AttachSize=? WHERE UUID=?"; @@ -825,4 +824,4 @@ namespace OpenWifi { return false; } -} // namespace OpenWifi \ No newline at end of file +} // namespace OpenWifi