• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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