1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <cstring>
17 #include <nlohmann/json.hpp>
18
19 #include "control_cmd_parser.h"
20 #include "dfs_error.h"
21 #include "parameter.h"
22 #include "system_notifier.h"
23 #include "utils_log.h"
24
25 namespace OHOS {
26 namespace Storage {
27 namespace DistributedFile {
28 using namespace FileManagement;
29 using json = nlohmann::json;
30
31 std::function<void(std::string)> ControlCmdParser::disconnectCallback_;
32
ParseFromJson(const std::string & jsonStr,ControlCmd & outCmd)33 bool ControlCmdParser::ParseFromJson(const std::string &jsonStr, ControlCmd &outCmd)
34 {
35 if (jsonStr.empty() || !json::accept(jsonStr)) {
36 LOGE("ParseFromJson: jsonStr is empty or invalid");
37 return false;
38 }
39
40 json j = json::parse(jsonStr, nullptr, false);
41 if (j.is_discarded()) {
42 LOGE("ParseFromJson: jsonStr is discarded");
43 return false;
44 }
45
46 // --- Required Fields Validation ---
47 if (!j.contains("msgId") || !j["msgId"].is_number_integer()) {
48 LOGE("ParseFromJson: msgId is missing or not an integer");
49 return false;
50 }
51 outCmd.msgId = j["msgId"].get<int32_t>();
52
53 if (!j.contains("msgType") || !j["msgType"].is_number_integer()) {
54 LOGE("ParseFromJson: msgType is missing or not an integer");
55 return false;
56 }
57 outCmd.msgType = j["msgType"].get<int32_t>();
58
59 // --- Optional Fields (parse only if present and valid) ---
60 if (j.contains("version") && j["version"].is_number_unsigned()) {
61 outCmd.version = j["version"].get<uint16_t>();
62 }
63
64 if (j.contains("msgBody") && j["msgBody"].is_string()) {
65 outCmd.msgBody = j["msgBody"].get<std::string>();
66 }
67
68 if (j.contains("networkId") && j["networkId"].is_string()) {
69 outCmd.networkId = j["networkId"].get<std::string>();
70 }
71 return true;
72 }
73
SerializeToJson(const ControlCmd & cmd,std::string & outJsonStr)74 bool ControlCmdParser::SerializeToJson(const ControlCmd &cmd, std::string &outJsonStr)
75 {
76 json j;
77 j["version"] = cmd.version;
78 j["msgId"] = cmd.msgId;
79 j["msgType"] = cmd.msgType;
80 j["msgBody"] = cmd.msgBody;
81 j["networkId"] = cmd.networkId;
82
83 constexpr auto indent = -1;
84 constexpr auto indent_char = ' ';
85 constexpr auto ensure_ascii = false;
86 constexpr auto error_handler = nlohmann::json::error_handler_t::replace;
87
88 outJsonStr = j.dump(indent, indent_char, ensure_ascii, error_handler);
89 return !outJsonStr.empty();
90 }
91
HandleRequest(const ControlCmd & inCmd,ControlCmd & outCmd)92 bool ControlCmdParser::HandleRequest(const ControlCmd &inCmd, ControlCmd &outCmd)
93 {
94 LOGI("HandleRequest typecode = %{public}d", inCmd.msgType);
95 switch (inCmd.msgType) {
96 case ControlCmdType::CMD_CHECK_ALLOW_CONNECT:
97 return CheckAllowConnect(inCmd, outCmd);
98 case ControlCmdType::CMD_PUBLISH_NOTIFICATION:
99 return PublishNotification(inCmd, outCmd);
100 case ControlCmdType::CMD_CANCEL_NOTIFICATION:
101 return CancelNotification(inCmd, outCmd);
102 case ControlCmdType::CMD_ACTIVE_DISCONNECT:
103 return DisconnectByRemote(inCmd, outCmd);
104 default:
105 LOGE("Cannot response request %{public}d: unknown transaction", inCmd.msgType);
106 return false;
107 }
108 }
109
CheckAllowConnect(const ControlCmd & inCmd,ControlCmd & outCmd)110 bool ControlCmdParser::CheckAllowConnect(const ControlCmd &inCmd, ControlCmd &outCmd)
111 {
112 outCmd.msgType = ControlCmdType::CMD_MSG_RESPONSE;
113 outCmd.msgId = inCmd.msgId;
114 outCmd.msgBody = "false";
115
116 const char *syncType = "1";
117 const int bufferLen = 10;
118 char paramOutBuf[bufferLen] = {0};
119 int ret = GetParameter(DETERMINE_DEVICE_TYPE_KEY, "", paramOutBuf, bufferLen);
120 LOGI("paramOutBuf: %{public}s, ret: %{public}d", paramOutBuf, ret);
121 if (ret > 0 && strncmp(paramOutBuf, syncType, strlen(syncType)) == 0) {
122 LOGI("Determining the e2e device succeeded.");
123 outCmd.msgBody = "true";
124 }
125 return true;
126 }
127
PublishNotification(const ControlCmd & inCmd,ControlCmd & outCmd)128 bool ControlCmdParser::PublishNotification(const ControlCmd &inCmd, ControlCmd &outCmd)
129 {
130 LOGI("publishNotification networkId = %{public}.6s", inCmd.networkId.c_str());
131 auto ret = SystemNotifier::GetInstance().CreateLocalLiveView(inCmd.networkId);
132 if (ret != E_OK) {
133 LOGE("Failed to publish notification. ret: %{public}d", ret);
134 return false;
135 }
136 return true;
137 }
138
CancelNotification(const ControlCmd & inCmd,ControlCmd & outCmd)139 bool ControlCmdParser::CancelNotification(const ControlCmd &inCmd, ControlCmd &outCmd)
140 {
141 LOGI("cancelNotification networkId = %{public}.6s", inCmd.networkId.c_str());
142 auto ret = SystemNotifier::GetInstance().DestroyNotifyByNetworkId(inCmd.networkId);
143 if (ret != E_OK) {
144 LOGE("Failed to cancel notification. ret: %{public}d", ret);
145 return false;
146 }
147 return true;
148 }
149
DisconnectByRemote(const ControlCmd & inCmd,ControlCmd & outCmd)150 bool ControlCmdParser::DisconnectByRemote(const ControlCmd &inCmd, ControlCmd &outCmd)
151 {
152 LOGI("DisconnectByRemote networkId = %{public}.6s", inCmd.networkId.c_str());
153 if (disconnectCallback_ == nullptr) {
154 LOGE("callback is null");
155 return false;
156 }
157 disconnectCallback_(inCmd.msgBody);
158 return true;
159 }
160
RegisterDisconnectCallback(std::function<void (std::string)> cb)161 void ControlCmdParser::RegisterDisconnectCallback(std::function<void(std::string)> cb)
162 {
163 LOGI("start RegisterDisconnectCallback function.");
164 disconnectCallback_ = cb;
165 }
166 } // namespace DistributedFile
167 } // namespace Storage
168 } // namespace OHOS