From 8cf7811ce5fe4ba43e6448b845ffc738caa41c18 Mon Sep 17 00:00:00 2001 From: wengchangcheng Date: Wed, 19 Apr 2023 15:41:24 +0800 Subject: [PATCH 1/2] Add base file for toolchain client 1. Add domain client 2. Add function manager 3. Add toolchain command line tool Issue: https://gitee.com/openharmony/arkcompiler_toolchain/issues/I6X1B1 Signed-off-by: wengchangcheng Change-Id: Ifdbad4f271b639e709f0df2c19676a6a399c8b06 --- tooling/client/BUILD.gn | 12 ++++++++++++ tooling/client/domain/debugger_client.cpp | 14 ++++++++++++++ tooling/client/domain/debugger_client.h | 14 ++++++++++++++ tooling/client/domain/heapprofiler_client.cpp | 14 ++++++++++++++ tooling/client/domain/heapprofiler_client.h | 14 ++++++++++++++ tooling/client/domain/profiler_client copy.h | 14 ++++++++++++++ tooling/client/domain/profiler_client.cpp | 14 ++++++++++++++ tooling/client/domain/profiler_client.h | 14 ++++++++++++++ tooling/client/domain/runtime_client.cpp | 14 ++++++++++++++ tooling/client/domain/runtime_client.h | 14 ++++++++++++++ tooling/client/manager/breakpoint_manager.cpp | 14 ++++++++++++++ tooling/client/manager/breakpoint_manager.h | 14 ++++++++++++++ tooling/client/manager/stack_manager.cpp | 14 ++++++++++++++ tooling/client/manager/stack_manager.h | 14 ++++++++++++++ tooling/client/manager/step_manager.cpp | 14 ++++++++++++++ tooling/client/manager/step_manager.h | 14 ++++++++++++++ tooling/client/manager/variable_manager.cpp | 14 ++++++++++++++ tooling/client/manager/variable_manager.h | 14 ++++++++++++++ tooling/client/toolchain_cli/BUILD.gn | 12 ++++++++++++ tooling/client/toolchain_cli/main.cpp | 14 ++++++++++++++ tooling/client/websocket/websocket_client.cpp | 14 ++++++++++++++ tooling/client/websocket/websocket_client.h | 14 ++++++++++++++ 22 files changed, 304 insertions(+) create mode 100644 tooling/client/BUILD.gn create mode 100644 tooling/client/domain/debugger_client.cpp create mode 100644 tooling/client/domain/debugger_client.h create mode 100644 tooling/client/domain/heapprofiler_client.cpp create mode 100644 tooling/client/domain/heapprofiler_client.h create mode 100644 tooling/client/domain/profiler_client copy.h create mode 100644 tooling/client/domain/profiler_client.cpp create mode 100644 tooling/client/domain/profiler_client.h create mode 100644 tooling/client/domain/runtime_client.cpp create mode 100644 tooling/client/domain/runtime_client.h create mode 100644 tooling/client/manager/breakpoint_manager.cpp create mode 100644 tooling/client/manager/breakpoint_manager.h create mode 100644 tooling/client/manager/stack_manager.cpp create mode 100644 tooling/client/manager/stack_manager.h create mode 100644 tooling/client/manager/step_manager.cpp create mode 100644 tooling/client/manager/step_manager.h create mode 100644 tooling/client/manager/variable_manager.cpp create mode 100644 tooling/client/manager/variable_manager.h create mode 100644 tooling/client/toolchain_cli/BUILD.gn create mode 100644 tooling/client/toolchain_cli/main.cpp create mode 100644 tooling/client/websocket/websocket_client.cpp create mode 100644 tooling/client/websocket/websocket_client.h diff --git a/tooling/client/BUILD.gn b/tooling/client/BUILD.gn new file mode 100644 index 00000000..242ddef1 --- /dev/null +++ b/tooling/client/BUILD.gn @@ -0,0 +1,12 @@ +# Copyright (c) 2021-2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/tooling/client/domain/debugger_client.cpp b/tooling/client/domain/debugger_client.cpp new file mode 100644 index 00000000..9703852d --- /dev/null +++ b/tooling/client/domain/debugger_client.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/tooling/client/domain/debugger_client.h b/tooling/client/domain/debugger_client.h new file mode 100644 index 00000000..9703852d --- /dev/null +++ b/tooling/client/domain/debugger_client.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/tooling/client/domain/heapprofiler_client.cpp b/tooling/client/domain/heapprofiler_client.cpp new file mode 100644 index 00000000..9703852d --- /dev/null +++ b/tooling/client/domain/heapprofiler_client.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/tooling/client/domain/heapprofiler_client.h b/tooling/client/domain/heapprofiler_client.h new file mode 100644 index 00000000..9703852d --- /dev/null +++ b/tooling/client/domain/heapprofiler_client.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/tooling/client/domain/profiler_client copy.h b/tooling/client/domain/profiler_client copy.h new file mode 100644 index 00000000..9703852d --- /dev/null +++ b/tooling/client/domain/profiler_client copy.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/tooling/client/domain/profiler_client.cpp b/tooling/client/domain/profiler_client.cpp new file mode 100644 index 00000000..9703852d --- /dev/null +++ b/tooling/client/domain/profiler_client.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/tooling/client/domain/profiler_client.h b/tooling/client/domain/profiler_client.h new file mode 100644 index 00000000..9703852d --- /dev/null +++ b/tooling/client/domain/profiler_client.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/tooling/client/domain/runtime_client.cpp b/tooling/client/domain/runtime_client.cpp new file mode 100644 index 00000000..9703852d --- /dev/null +++ b/tooling/client/domain/runtime_client.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/tooling/client/domain/runtime_client.h b/tooling/client/domain/runtime_client.h new file mode 100644 index 00000000..9703852d --- /dev/null +++ b/tooling/client/domain/runtime_client.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/tooling/client/manager/breakpoint_manager.cpp b/tooling/client/manager/breakpoint_manager.cpp new file mode 100644 index 00000000..9703852d --- /dev/null +++ b/tooling/client/manager/breakpoint_manager.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/tooling/client/manager/breakpoint_manager.h b/tooling/client/manager/breakpoint_manager.h new file mode 100644 index 00000000..9703852d --- /dev/null +++ b/tooling/client/manager/breakpoint_manager.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/tooling/client/manager/stack_manager.cpp b/tooling/client/manager/stack_manager.cpp new file mode 100644 index 00000000..9703852d --- /dev/null +++ b/tooling/client/manager/stack_manager.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/tooling/client/manager/stack_manager.h b/tooling/client/manager/stack_manager.h new file mode 100644 index 00000000..9703852d --- /dev/null +++ b/tooling/client/manager/stack_manager.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/tooling/client/manager/step_manager.cpp b/tooling/client/manager/step_manager.cpp new file mode 100644 index 00000000..9703852d --- /dev/null +++ b/tooling/client/manager/step_manager.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/tooling/client/manager/step_manager.h b/tooling/client/manager/step_manager.h new file mode 100644 index 00000000..9703852d --- /dev/null +++ b/tooling/client/manager/step_manager.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/tooling/client/manager/variable_manager.cpp b/tooling/client/manager/variable_manager.cpp new file mode 100644 index 00000000..9703852d --- /dev/null +++ b/tooling/client/manager/variable_manager.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/tooling/client/manager/variable_manager.h b/tooling/client/manager/variable_manager.h new file mode 100644 index 00000000..9703852d --- /dev/null +++ b/tooling/client/manager/variable_manager.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/tooling/client/toolchain_cli/BUILD.gn b/tooling/client/toolchain_cli/BUILD.gn new file mode 100644 index 00000000..242ddef1 --- /dev/null +++ b/tooling/client/toolchain_cli/BUILD.gn @@ -0,0 +1,12 @@ +# Copyright (c) 2021-2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/tooling/client/toolchain_cli/main.cpp b/tooling/client/toolchain_cli/main.cpp new file mode 100644 index 00000000..9703852d --- /dev/null +++ b/tooling/client/toolchain_cli/main.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/tooling/client/websocket/websocket_client.cpp b/tooling/client/websocket/websocket_client.cpp new file mode 100644 index 00000000..9703852d --- /dev/null +++ b/tooling/client/websocket/websocket_client.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/tooling/client/websocket/websocket_client.h b/tooling/client/websocket/websocket_client.h new file mode 100644 index 00000000..9703852d --- /dev/null +++ b/tooling/client/websocket/websocket_client.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -- Gitee From c0f6758e7f6c62c454501bcf26e115608bacd502 Mon Sep 17 00:00:00 2001 From: caolili123 Date: Fri, 30 Jun 2023 11:07:34 +0800 Subject: [PATCH 2/2] issue:https://gitee.com/openharmony/arkcompiler_toolchain/issues/I7HB8J Signed-off-by: caolili123 --- BUILD.gn | 1 + tooling/client/BUILD.gn | 57 ++- tooling/client/toolchain_cli/BUILD.gn | 49 ++- tooling/client/toolchain_cli/cli_command.cpp | 298 +++++++++++++ tooling/client/toolchain_cli/cli_command.h | 90 ++++ tooling/client/toolchain_cli/main.cpp | 96 ++++ tooling/client/websocket/websocket_client.cpp | 414 ++++++++++++++++++ tooling/client/websocket/websocket_client.h | 66 +++ 8 files changed, 1069 insertions(+), 2 deletions(-) create mode 100644 tooling/client/toolchain_cli/cli_command.cpp create mode 100644 tooling/client/toolchain_cli/cli_command.h diff --git a/BUILD.gn b/BUILD.gn index ac0d92d4..18318125 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -129,6 +129,7 @@ group("ark_toolchain_packages") { "$toolchain_root/inspector:ark_debugger", "$toolchain_root/inspector:connectserver_debugger", "$toolchain_root/tooling:libark_ecma_debugger", + "$toolchain_root/tooling/client/toolchain_cli:toolchain_cli" ] } } diff --git a/tooling/client/BUILD.gn b/tooling/client/BUILD.gn index 242ddef1..0a396b3f 100644 --- a/tooling/client/BUILD.gn +++ b/tooling/client/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022 Huawei Device Co., Ltd. +# Copyright (c) 2023 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -10,3 +10,58 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + +import("//arkcompiler/toolchain/toolchain.gni") + +config("hiviewdfx_config") { + defines = [] + if (enable_dump_in_faultlog) { + defines += [ "ENABLE_DUMP_IN_FAULTLOG" ] + } + if (enable_bytrace) { + defines += [ "ENABLE_BYTRACE" ] + cflags_cc = [ "-Wno-gnu-zero-variadic-macro-arguments" ] + } + if (enable_hitrace) { + defines += [ "ENABLE_HITRACE" ] + } + if (enable_hilog) { + defines += [ "ENABLE_HILOG" ] + } + + include_dirs = [ "$hilog_root/include" ] +} + +ohos_source_set("websocket_client") { + stack_protector_ret = false + defines = [] + deps = [] + configs = [] + + # hiviewdfx libraries + external_deps = hiviewdfx_ext_deps + deps += hiviewdfx_deps + + include_dirs = [ + "$toolchain_root", + "$toolchain_root/inspector", + "$toolchain_root/websocket", + "$toolchain_root/tooling/client", + ] + + sources = [ "websocket/websocket_client.cpp" ] + + deps += [ + "$toolchain_root/websocket:websocket", + "$ark_third_party_root/openssl:libcrypto_shared", + sdk_libc_secshared_dep, + ] + + configs += [ + ":hiviewdfx_config", + ] + + subsystem_name = "arkcompiler" + part_name = "toolchain" +} + diff --git a/tooling/client/toolchain_cli/BUILD.gn b/tooling/client/toolchain_cli/BUILD.gn index 242ddef1..015a9095 100644 --- a/tooling/client/toolchain_cli/BUILD.gn +++ b/tooling/client/toolchain_cli/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022 Huawei Device Co., Ltd. +# Copyright (c) 2023 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -10,3 +10,50 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + +import("//arkcompiler/toolchain/toolchain.gni") + +config("hiviewdfx_config") { + defines = [] + if (enable_dump_in_faultlog) { + defines += [ "ENABLE_DUMP_IN_FAULTLOG" ] + } + if (enable_bytrace) { + defines += [ "ENABLE_BYTRACE" ] + cflags_cc = [ "-Wno-gnu-zero-variadic-macro-arguments" ] + } + if (enable_hitrace) { + defines += [ "ENABLE_HITRACE" ] + } + if (enable_hilog) { + defines += [ "ENABLE_HILOG" ] + } + + include_dirs = [ "$hilog_root/include" ] +} + +ohos_executable("toolchain_cli") { + sources = [ + "main.cpp", + "cli_command.cpp", + ] + + include_dirs = [ + "$toolchain_root", + "$toolchain_root/tooling", + "$toolchain_root/inspector", + "$toolchain_root/websocket", + "$toolchain_root/tooling/client/toolchain_cli", + ] + + deps = [ + "$toolchain_root/tooling/client:websocket_client", + ] + + configs = [ ":hiviewdfx_config" ] + + install_enable = false + + part_name = "toolchain" + subsystem_name = "arkcompiler" +} diff --git a/tooling/client/toolchain_cli/cli_command.cpp b/tooling/client/toolchain_cli/cli_command.cpp new file mode 100644 index 00000000..9b54affe --- /dev/null +++ b/tooling/client/toolchain_cli/cli_command.cpp @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "cli_command.h" +#include "log_wrapper.h" + +namespace OHOS::ArkCompiler::Toolchain{ +const std::string HELP_MSG = "usage: \n" + " These are common commands list:\n" + " allocationtrack(at) allocation-track-start with options\n" + " break(b) break with options\n" + " backtrack(bt) backtrace\n" + " continue(c) continue\n" + " cpuprofile(cp) cpu-profile-start with options\n" + " delete(d) delete with options\n" + " disable disable\n" + " display display\n" + " enable enable\n" + " finish(fin) finish\n" + " frame(f) frame\n" + " heapdump(hd) heapdump with options\n" + " help(h) list available commands\n" + " ignore(ig) ignore\n" + " infobreakpoints(infob) info-breakpoints\n" + " infosource(infos) info-source\n" + " jump(j) jump\n" + " list(l) list\n" + " next(n) next\n" + " print(p) print with options\n" + " ptype ptype\n" + " quit(q) quit\n" + " run(r) run\n" + " setvar(sv) set value with options\n" + " step(s) step\n" + " undisplay undisplay\n" + " watch watch\n"; + +const std::vector cmdList = { + "allocationtrack", + "break", + "backtrack", + "continue", + "cpuprofile", + "delete", + "disable", + "display", + "enable", + "finish", + "frame", + "heapdump", + "help", + "ignore", + "infobreakpoints", + "infosource", + "jump", + "list", + "next", + "print", + "ptype", + "run", + "setvar", + "step", + "undisplay", + "watch" +}; +std::string CliCommand::ExecCommand() +{ + + int result = CreateCommandMap(); + if (result != ERR_OK) { + LOGE("failed to create command map."); + } + + result = OnCommand(); + if (result != ERR_OK) { + LOGE("failed to execute your command."); + resultReceiver_ = "error: failed to execute your command.\n"; + } + return resultReceiver_; +} + +ErrCode CliCommand::CreateCommandMap() +{ + commandMap_ = { + {std::make_pair("allocationtrack","at"), std::bind(&CliCommand::ExecAllocationTrackCommand, this)}, + {std::make_pair("break","b"), std::bind(&CliCommand::ExecBreakCommand, this)}, + {std::make_pair("backtrack","bt"), std::bind(&CliCommand::ExecBackTrackCommand, this)}, + {std::make_pair("continue","c"), std::bind(&CliCommand::ExecContinueCommand, this)}, + {std::make_pair("cpuprofile","cp"), std::bind(&CliCommand::ExecCpuProfileCommand, this)}, + {std::make_pair("delete","d"), std::bind(&CliCommand::ExecDeleteCommand, this)}, + {std::make_pair("disable","disable"), std::bind(&CliCommand::ExecDisableCommand, this)}, + {std::make_pair("display","display"), std::bind(&CliCommand::ExecDisplayCommand, this)}, + {std::make_pair("enable","enable"), std::bind(&CliCommand::ExecEnableCommand, this)}, + {std::make_pair("finish","fin"), std::bind(&CliCommand::ExecFinishCommand, this)}, + {std::make_pair("frame","f"), std::bind(&CliCommand::ExecFrameCommand, this)}, + {std::make_pair("heapdump","hd"), std::bind(&CliCommand::ExecHeapDumpCommand, this)}, + {std::make_pair("help","h"), std::bind(&CliCommand::ExecHelpCommand, this)}, + {std::make_pair("ignore","ig"), std::bind(&CliCommand::ExecIgnoreCommand, this)}, + {std::make_pair("infobreakpoints","infob"), std::bind(&CliCommand::ExecInfoBCommand, this)}, + {std::make_pair("infosource","infos"), std::bind(&CliCommand::ExecInfoSCommand, this)}, + {std::make_pair("jump","j"), std::bind(&CliCommand::ExecJumpCommand, this)}, + {std::make_pair("list","l"), std::bind(&CliCommand::ExecListCommand, this)}, + {std::make_pair("next","n"), std::bind(&CliCommand::ExecNextCommand, this)}, + {std::make_pair("print","p"), std::bind(&CliCommand::ExecPrintCommand, this)}, + {std::make_pair("ptype","ptype"), std::bind(&CliCommand::ExecPtypeCommand, this)}, + {std::make_pair("run","r"), std::bind(&CliCommand::ExecRunCommand, this)}, + {std::make_pair("setvar","sv"), std::bind(&CliCommand::ExecSetValueCommand, this)}, + {std::make_pair("step","s"), std::bind(&CliCommand::ExecStepCommand, this)}, + {std::make_pair("undisplay","undisplay"), std::bind(&CliCommand::ExecUndisplayCommand, this)}, + {std::make_pair("watch","wa"), std::bind(&CliCommand::ExecWatchCommand, this)}, + }; + + return ERR_OK; +} + +ErrCode CliCommand::ExecAllocationTrackCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::ExecBreakCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::ExecBackTrackCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::ExecContinueCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::ExecCpuProfileCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::ExecDeleteCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::ExecDisableCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::ExecDisplayCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::ExecEnableCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::ExecFinishCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::ExecFrameCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::ExecHeapDumpCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::ExecHelpCommand() +{ + std::cout << HELP_MSG; + return ERR_OK; +} + +ErrCode CliCommand::ExecIgnoreCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::ExecInfoBCommand() +{ + return ERR_OK; +} +ErrCode CliCommand::ExecInfoSCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::ExecJumpCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::ExecListCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::ExecNextCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::ExecPrintCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::ExecPtypeCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::ExecRunCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::ExecSetValueCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::ExecStepCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::ExecUndisplayCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::ExecWatchCommand() +{ + return ERR_OK; +} + +ErrCode CliCommand::OnCommand() +{ + std::map>::iterator it; + StrPair cmdPair; + bool firstFlag = false; + + for (it = commandMap_.begin(); it != commandMap_.end(); it++) { + cmdPair = it->first; + if (!strcmp(cmdPair.first.c_str(), cmd_.c_str()) + ||!strcmp(cmdPair.second.c_str(), cmd_.c_str())) { + auto respond = it->second; + respond(); + std::cout << "exe success, cmd is " << cmd_ << std::endl; + return ERR_OK; + } + } + + for(unsigned int i = 0; i < cmdList.size(); i++) { + if (!strncmp(cmdList[i].c_str(), cmd_.c_str(), std::strlen(cmd_.c_str()))) { + if (!firstFlag) { + std::cout << ">>>"; + firstFlag = true; + } + std::cout << " " << cmdList[i]; + } + } + + if (firstFlag) { + std::cout << std::endl; + } else { + ExecHelpCommand(); + } + + return ERR_OK; +} + +} // namespace OHOS::ArkCompiler::Toolchain diff --git a/tooling/client/toolchain_cli/cli_command.h b/tooling/client/toolchain_cli/cli_command.h new file mode 100644 index 00000000..a3896038 --- /dev/null +++ b/tooling/client/toolchain_cli/cli_command.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMASCRIPT_TOOLING_CLIENT_TOOLCHAIN_CLI_COMMAND_H +#define ECMASCRIPT_TOOLING_CLIENT_TOOLCHAIN_CLI_COMMAND_H + +#include +#include +#include +#include +#include "../websocket/websocket_client.h" +#include "log_wrapper.h" + +namespace OHOS::ArkCompiler::Toolchain{ +using ErrCode = int; +using StrPair = std::pair; +using VecStr = std::vector; +enum { + ERR_OK = 0, + ERR_FAIL = 1 +}; + +class CliCommand { +public: + CliCommand(ToolchainWebsocket* cliSocket, std::vector cliCmdStr) + { + cliSocket_ = std::move(cliSocket); + cmd_ = cliCmdStr[0]; + for (unsigned int i = 1; i < cliCmdStr.size(); i++) { + argList_.push_back(cliCmdStr[i]); + } + } + + ~CliCommand() + { + } + + ErrCode OnCommand(); + std::string ExecCommand(); + std::string GetCommand(const std::string &str); + ErrCode CreateCommandMap(); + ErrCode ExecAllocationTrackCommand(); + ErrCode ExecBreakCommand(); + ErrCode ExecBackTrackCommand(); + ErrCode ExecContinueCommand(); + ErrCode ExecCpuProfileCommand(); + ErrCode ExecDeleteCommand(); + ErrCode ExecDisableCommand(); + ErrCode ExecDisplayCommand(); + ErrCode ExecEnableCommand(); + ErrCode ExecFinishCommand(); + ErrCode ExecFrameCommand(); + ErrCode ExecHeapDumpCommand(); + ErrCode ExecHelpCommand(); + ErrCode ExecIgnoreCommand(); + ErrCode ExecInfoBCommand(); + ErrCode ExecInfoSCommand(); + ErrCode ExecJumpCommand(); + ErrCode ExecListCommand(); + ErrCode ExecNextCommand(); + ErrCode ExecPrintCommand(); + ErrCode ExecPtypeCommand(); + ErrCode ExecRunCommand(); + ErrCode ExecSetValueCommand(); + ErrCode ExecStepCommand(); + ErrCode ExecUndisplayCommand(); + ErrCode ExecWatchCommand(); + +private: + std::string cmd_; + VecStr argList_; + std::map> commandMap_; + std::string resultReceiver_ = ""; + ToolchainWebsocket* cliSocket_ {nullptr}; +}; +} // namespace OHOS::ArkCompiler::Toolchain + +#endif //ECMASCRIPT_TOOLING_CLIENT_TOOLCHAIN_CLI_COMMAND_H \ No newline at end of file diff --git a/tooling/client/toolchain_cli/main.cpp b/tooling/client/toolchain_cli/main.cpp index 9703852d..af7eba39 100644 --- a/tooling/client/toolchain_cli/main.cpp +++ b/tooling/client/toolchain_cli/main.cpp @@ -12,3 +12,99 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#include +#include +#include + +#include "cli_command.h" + +namespace OHOS::ArkCompiler::Toolchain{ +bool StrToUInt(const char *content, uint32_t *result) +{ + const int DEC = 10; + char *endPtr = nullptr; + *result = std::strtoul(content, &endPtr, DEC); + if (endPtr == content || *endPtr != '\0') { + return false; + } + return true; +} + +std::vector SplitString(const std::string &str, const std::string &delimiter) +{ + std::size_t strIndex = 0; + std::vector value; + std::size_t pos = str.find_first_of(delimiter, strIndex); + while ((pos < str.size()) && (pos > strIndex)) { + std::string subStr = str.substr(strIndex, pos - strIndex); + value.push_back(std::move(subStr)); + strIndex = pos; + strIndex = str.find_first_not_of(delimiter, strIndex); + pos = str.find_first_of(delimiter, strIndex); + } + if (pos > strIndex) { + std::string subStr = str.substr(strIndex, pos - strIndex); + if (!subStr.empty()) { + value.push_back(std::move(subStr)); + } + } + return value; +} + +int Main(const int argc, const char** argv) +{ + uint32_t port = 0; + OHOS::ArkCompiler::Toolchain::ToolchainWebsocket cliSocket; + if(argc < 2) { + LOGE("toolchain_cli is missing a parameter"); + return -1; + } + if(strstr(argv[0], "toolchain_cli") != nullptr) { + if(StrToUInt(argv[1], &port)) { + if((port <= 0) || (port >= 65535)) { + LOGE("toolchain_cli:InitToolchainWebSocketForPort the port = %{public}d is wrong.", port); + return -1; + } + if(!cliSocket.InitToolchainWebSocketForPort(port, 5)) { + LOGE("toolchain_cli:InitToolchainWebSocketForPort failed"); + return -1; + } + } else { + if(!cliSocket.InitToolchainWebSocketForSockName(argv[1])) { + LOGE("toolchain_cli:InitToolchainWebSocketForSockName failed"); + return -1; + } + } + + if (!cliSocket.ClientSendWSUpgradeReq()) { + LOGE("toolchain_cli:ClientSendWSUpgradeReq failed"); + return -1; + } + if (!cliSocket.ClientRecvWSUpgradeRsp()) { + LOGE("toolchain_cli:ClientRecvWSUpgradeRsp failed"); + return -1; + } + + std::cout << ">>> "; + std::string inputStr; + while(getline(std::cin, inputStr)) { + if((!strcmp(inputStr.c_str(), "quit"))||(!strcmp(inputStr.c_str(), "q"))) { + LOGE("toolchain_cli: quit"); + cliSocket.Close(); + break; + } + std::vector cliCmdStr = SplitString(inputStr, " "); + OHOS::ArkCompiler::Toolchain::CliCommand cmd(&cliSocket, cliCmdStr); + std::cout << cmd.ExecCommand(); + std::cout << ">>> "; + } + } + return 0; +} +} //OHOS::ArkCompiler::Toolchain + +int main(int argc, const char **argv) +{ + return OHOS::ArkCompiler::Toolchain::Main(argc, argv); +} diff --git a/tooling/client/websocket/websocket_client.cpp b/tooling/client/websocket/websocket_client.cpp index 9703852d..cfc3c564 100644 --- a/tooling/client/websocket/websocket_client.cpp +++ b/tooling/client/websocket/websocket_client.cpp @@ -12,3 +12,417 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include +#include +#include +#include +#include +#include + +#include "log_wrapper.h" +#include "websocket_client.h" + + +namespace OHOS::ArkCompiler::Toolchain { +bool ToolchainWebsocket::InitToolchainWebSocketForPort (int port, uint32_t timeoutLimit) +{ + if (socketState_ != ToolchainSocketState::UNINITED) { + LOGE("InitToolchainWebSocketForPort::client has inited."); + return true; + } + + client_ = socket(AF_INET, SOCK_STREAM, 0); + if (client_ < SOCKET_SUCCESS) { + LOGE("InitToolchainWebSocketForPort::client socket failed, error = %{public}d , desc = %{public}s", + errno, strerror(errno)); + return false; + } + + // set send and recv timeout limit + if (!SetWebSocketTimeOut(client_, timeoutLimit)) { + LOGE("InitToolchainWebSocketForPort::client SetWebSocketTimeOut failed, error = %{public}d , desc = %{public}s", + errno, strerror(errno)); + close(client_); + client_ = -1; + return false; + } + + sockaddr_in clientAddr; + if (memset_s(&clientAddr, sizeof(clientAddr), 0, sizeof(clientAddr)) != EOK) { + LOGE("InitToolchainWebSocketForPort::client memset_s clientAddr failed, error = %{public}d, desc = %{public}s", + errno, strerror(errno)); + close(client_); + client_ = -1; + return false; + } + clientAddr.sin_family = AF_INET; + clientAddr.sin_port = htons(port); + if (int ret = inet_pton(AF_INET, "127.0.0.1", &clientAddr.sin_addr) < NET_SUCCESS) { + LOGE("InitToolchainWebSocketForPort::client inet_pton failed, error = %{public}d, desc = %{public}s", + errno, strerror(errno)); + close(client_); + client_ = -1; + return false; + } + + int ret = connect(client_, reinterpret_cast(&clientAddr), sizeof(clientAddr)); + if (ret != SOCKET_SUCCESS) { + LOGE("InitToolchainWebSocketForPort::client connect failed, error = %{public}d, desc = %{public}s", + errno, strerror(errno)); + close(client_); + client_ = -1; + return false; + } + socketState_ = ToolchainSocketState::INITED; + LOGE("InitToolchainWebSocketForPort::client connect success."); + return true; +} + +bool ToolchainWebsocket::InitToolchainWebSocketForSockName(const std::string &sockName, uint32_t timeoutLimit) +{ + if (socketState_ != ToolchainSocketState::UNINITED) { + LOGE("InitToolchainWebSocketForSockName::client has inited."); + return true; + } + + client_ = socket(AF_UNIX, SOCK_STREAM, 0); + if (client_ < SOCKET_SUCCESS) { + LOGE("InitToolchainWebSocketForSockName::client socket failed, error = %{public}d , desc = %{public}s", + errno, strerror(errno)); + return false; + } + + // set send and recv timeout limit + if (!SetWebSocketTimeOut(client_, timeoutLimit)) { + LOGE("InitToolchainWebSocketForSockName::client SetWebSocketTimeOut failed, error = %{public}d ,\ + desc = %{public}s", errno, strerror(errno)); + close(client_); + client_ = -1; + return false; + } + + struct sockaddr_un serverAddr; + if (memset_s(&serverAddr, sizeof(serverAddr), 0, sizeof(serverAddr)) != EOK) { + LOGE("InitToolchainWebSocketForSockName::client memset_s clientAddr failed, error = %{public}d,\ + desc = %{public}s", errno, strerror(errno)); + close(client_); + client_ = -1; + return false; + } + serverAddr.sun_family = AF_UNIX; + if (strcpy_s(serverAddr.sun_path + 1, sizeof(serverAddr.sun_path) - 1, sockName.c_str()) != EOK) { + LOGE("InitToolchainWebSocketForSockName::client strcpy_s serverAddr.sun_path failed, error = %{public}d,\ + desc = %{public}s", errno, strerror(errno)); + close(client_); + client_ = -1; + return false; + } + serverAddr.sun_path[0] = '\0'; + + uint32_t len = offsetof(struct sockaddr_un, sun_path) + strlen(sockName.c_str()) + 1; + int ret = connect(client_, reinterpret_cast(&serverAddr), static_cast(len)); + if (ret != SOCKET_SUCCESS) { + LOGE("InitToolchainWebSocketForSockName::client connect failed, error = %{public}d, desc = %{public}s", + errno, strerror(errno)); + close(client_); + client_ = -1; + return false; + } + socketState_ = ToolchainSocketState::INITED; + LOGE("InitToolchainWebSocketForSockName::client connect success."); + return true; +} + +bool ToolchainWebsocket::ClientSendWSUpgradeReq() +{ + if (socketState_ == ToolchainSocketState::UNINITED) { + LOGE("ClientSendWSUpgradeReq::client has not inited."); + return false; + } + if (socketState_ == ToolchainSocketState::CONNECTED) { + LOGE("ClientSendWSUpgradeReq::client has connected."); + return true; + } + + int msgLen = strlen(CLIENT_WEBSOCKET_UPGRADE_REQ); + int32_t sendLen = send(client_, CLIENT_WEBSOCKET_UPGRADE_REQ, msgLen, 0); + if (sendLen != msgLen) { + LOGE("ClientSendWSUpgradeReq::client send wsupgrade req failed, error = %{public}d, desc = %{public}sn", + errno, strerror(errno)); + socketState_ = ToolchainSocketState::UNINITED; + close(client_); + client_ = -1; + return false; + } + LOGE("ClientSendWSUpgradeReq::client send wsupgrade req success."); + return true; +} + +bool ToolchainWebsocket::ClientRecvWSUpgradeRsp() +{ + if (socketState_ == ToolchainSocketState::UNINITED) { + LOGE("ClientRecvWSUpgradeRsp::client has not inited."); + return false; + } + if (socketState_ == ToolchainSocketState::CONNECTED) { + LOGE("ClientRecvWSUpgradeRsp::client has connected."); + return true; + } + + char recvBuf[CLIENT_WEBSOCKET_UPGRADE_RSP_LEN + 1] = {0}; + int32_t bufLen = recv(client_, recvBuf, CLIENT_WEBSOCKET_UPGRADE_RSP_LEN, 0); + if (bufLen != CLIENT_WEBSOCKET_UPGRADE_RSP_LEN) { + LOGE("ClientRecvWSUpgradeRsp::client recv wsupgrade rsp failed, error = %{public}d, desc = %{public}sn", + errno, strerror(errno)); + socketState_ = ToolchainSocketState::UNINITED; + close(client_); + client_ = -1; + return false; + } + socketState_ = ToolchainSocketState::CONNECTED; + LOGE("ClientRecvWSUpgradeRsp::client recv wsupgrade rsp success."); + return true; +} + +bool ToolchainWebsocket::ClientSendReq(const std::string &message) +{ + if (socketState_ != ToolchainSocketState::CONNECTED) { + LOGE("ClientSendReq::client has not connected."); + return false; + } + + uint32_t msgLen = message.length(); + std::unique_ptr msgBuf = std::make_unique(msgLen + 15); // 15: the maximum expand length + char *sendBuf = msgBuf.get(); + uint32_t sendMsgLen = 0; + sendBuf[0] = 0x81; // 0x81: the text message sent by the server should start with '0x81'. + uint32_t mask = 1; + // Depending on the length of the messages, client will use shift operation to get the res + // and store them in the buffer. + if (msgLen <= 125) { // 125: situation 1 when message's length <= 125 + sendBuf[1] = msgLen | (mask << 7); // 7: mask need shift left by 7 bits + sendMsgLen = 2; // 2: the length of header frame is 2; + } else if (msgLen < 65536) { // 65536: message's length + sendBuf[1] = 126 | (mask << 7); // 126: payloadLen according to the spec; 7: mask shift left by 7 bits + sendBuf[2] = ((msgLen >> 8) & 0xff); // 8: shift right by 8 bits => res * (256^1) + sendBuf[3] = (msgLen & 0xff); // 3: store len's data => res * (256^0) + sendMsgLen = 4; // 4: the length of header frame is 4 + } else { + sendBuf[1] = 127 | (mask << 7); // 127: payloadLen according to the spec; 7: mask shift left by 7 bits + for (int32_t i = 2; i <= 5; i++) { // 2 ~ 5: unused bits + sendBuf[i] = 0; + } + sendBuf[6] = ((msgLen & 0xff000000) >> 24); // 6: shift 24 bits => res * (256^3) + sendBuf[7] = ((msgLen & 0x00ff0000) >> 16); // 7: shift 16 bits => res * (256^2) + sendBuf[8] = ((msgLen & 0x0000ff00) >> 8); // 8: shift 8 bits => res * (256^1) + sendBuf[9] = (msgLen & 0x000000ff); // 9: res * (256^0) + sendMsgLen = 10; // 10: the length of header frame is 10 + } + + if (memcpy_s(sendBuf + sendMsgLen, SOCKET_MASK_LEN, MASK_KEY, SOCKET_MASK_LEN) != EOK) { + LOGE("ClientSendReq::client memcpy_s MASK_KEY failed, error = %{public}d, desc = %{public}s", + errno, strerror(errno)); + return false; + } + sendMsgLen += SOCKET_MASK_LEN; + + std::string maskMessage; + for (uint64_t i = 0; i < msgLen; i++) { + uint64_t j = i % SOCKET_MASK_LEN; + maskMessage.push_back(message[i] ^ MASK_KEY[j]); + } + if (memcpy_s(sendBuf + sendMsgLen, msgLen, maskMessage.c_str(), msgLen) != EOK) { + LOGE("ClientSendReq::client memcpy_s maskMessage failed, error = %{public}d, desc = %{public}s", + errno, strerror(errno)); + return false; + } + msgBuf[sendMsgLen + msgLen] = '\0'; + + if (send(client_, sendBuf, sendMsgLen + msgLen, 0) != static_cast(sendMsgLen + msgLen)) { + LOGE("ClientSendReq::client send msg req failed, error = %{public}d, desc = %{public}s", + errno, strerror(errno)); + return false; + } + LOGE("ClientRecvWSUpgradeRsp::client send msg req success."); + return true; +} + +std::string ToolchainWebsocket::Decode() +{ + if (socketState_ != ToolchainSocketState::CONNECTED) { + LOGE("ToolchainWebsocket:Decode failed, websocket not connected!"); + return ""; + } + char recvbuf[SOCKET_HEADER_LEN + 1]; + if (!Recv(client_, recvbuf, SOCKET_HEADER_LEN, 0)) { + LOGE("ToolchainWebsocket:Decode failed, client websocket disconnect"); + socketState_ = ToolchainSocketState::INITED; + close(client_); + client_ = -1; + return ""; + } + ToolchainWebSocketFrame wsFrame; + int32_t index = 0; + wsFrame.fin = static_cast(recvbuf[index] >> 7); // 7: shift right by 7 bits to get the fin + wsFrame.opcode = static_cast(recvbuf[index] & 0xf); + if (wsFrame.opcode == 0x1) { // 0x1: 0x1 means a text frame + index++; + wsFrame.mask = static_cast((recvbuf[index] >> 7) & 0x1); // 7: to get the mask + wsFrame.payloadLen = recvbuf[index] & 0x7f; + if (HandleFrame(wsFrame)) { + return wsFrame.payload.get(); + } + return ""; + } else if (wsFrame.opcode == 0x9) { // 0x9: 0x9 means a ping frame + // send pong frame + char pongFrame[SOCKET_HEADER_LEN] = {0}; + pongFrame[0] = 0x8a; // 0x8a: 0x8a means a pong frame + pongFrame[1] = 0x0; + if (!Send(client_, pongFrame, SOCKET_HEADER_LEN, 0)) { + LOGE("ToolchainWebsocket Decode: Send pong frame failed"); + return ""; + } + } + return ""; +} + +bool ToolchainWebsocket::HandleFrame(ToolchainWebSocketFrame& wsFrame) +{ + if (wsFrame.payloadLen == 126) { // 126: the payloadLen read from frame + char recvbuf[PAYLOAD_LEN + 1] = {0}; + if (!Recv(client_, recvbuf, PAYLOAD_LEN, 0)) { + LOGE("ToolchainWebsocket HandleFrame: Recv payloadLen == 126 failed"); + return false; + } + + uint16_t msgLen = 0; + if (memcpy_s(&msgLen, sizeof(recvbuf), recvbuf, sizeof(recvbuf) - 1) != EOK) { + LOGE("ToolchainWebsocket HandleFrame: memcpy_s failed"); + return false; + } + wsFrame.payloadLen = ntohs(msgLen); + } else if (wsFrame.payloadLen > 126) { // 126: the payloadLen read from frame + char recvbuf[EXTEND_PAYLOAD_LEN + 1] = {0}; + if (!Recv(client_, recvbuf, EXTEND_PAYLOAD_LEN, 0)) { + LOGE("ToolchainWebsocket HandleFrame: Recv payloadLen > 127 failed"); + return false; + } + wsFrame.payloadLen = NetToHostLongLong(recvbuf, EXTEND_PAYLOAD_LEN); + } + return DecodeMessage(wsFrame); +} + +bool ToolchainWebsocket::DecodeMessage(ToolchainWebSocketFrame& wsFrame) +{ + if (wsFrame.payloadLen == 0 || wsFrame.payloadLen > UINT64_MAX) { + LOGE("ToolchainWebsocket:ReadMsg length error, expected greater than zero and less than UINT64_MAX"); + return false; + } + uint64_t msgLen = wsFrame.payloadLen; + wsFrame.payload = std::make_unique(msgLen + 1); + if (wsFrame.mask == 1) { + char buf[msgLen + 1]; + if (!Recv(client_, wsFrame.maskingkey, SOCKET_MASK_LEN, 0)) { + LOGE("ToolchainWebsocket DecodeMessage: Recv maskingkey failed"); + return false; + } + + if (!Recv(client_, buf, msgLen, 0)) { + LOGE("ToolchainWebsocket DecodeMessage: Recv message with mask failed"); + return false; + } + + for (uint64_t i = 0; i < msgLen; i++) { + uint64_t j = i % SOCKET_MASK_LEN; + wsFrame.payload.get()[i] = buf[i] ^ wsFrame.maskingkey[j]; + } + } else { + char buf[msgLen + 1]; + if (!Recv(client_, buf, msgLen, 0)) { + LOGE("ToolchainWebsocket DecodeMessage: Recv message without mask failed"); + return false; + } + + if (memcpy_s(wsFrame.payload.get(), msgLen, buf, msgLen) != EOK) { + LOGE("ToolchainWebsocket DecodeMessage: memcpy_s failed"); + return false; + } + } + wsFrame.payload.get()[msgLen] = '\0'; + return true; +} + +uint64_t ToolchainWebsocket::NetToHostLongLong(char* buf, uint32_t len) +{ + uint64_t result = 0; + for (uint32_t i = 0; i < len; i++) { + result |= static_cast(buf[i]); + if ((i + 1) < len) { + result <<= 8; // 8: result need shift left 8 bits in order to big endian convert to int + } + } + return result; +} + +bool ToolchainWebsocket::Send(int32_t fd, const char* buf, size_t totalLen, int32_t flags) const +{ + size_t sendLen = 0; + while (sendLen < totalLen) { + ssize_t len = send(fd, buf + sendLen, totalLen - sendLen, flags); + if (len <= 0) { + LOGE("ToolchainWebsocket Send Message in while failed, ToolchainWebsocket disconnect"); + return false; + } + sendLen += static_cast(len); + } + return true; +} + +bool ToolchainWebsocket::Recv(int32_t fd, char* buf, size_t totalLen, int32_t flags) const +{ + size_t recvLen = 0; + while (recvLen < totalLen) { + ssize_t len = recv(fd, buf + recvLen, totalLen - recvLen, flags); + if (len <= 0) { + LOGE("ToolchainWebsocket Recv payload in while failed, ToolchainWebsocket disconnect"); + return false; + } + recvLen += static_cast(len); + } + buf[totalLen] = '\0'; + return true; +} + +void ToolchainWebsocket::Close() +{ + if (socketState_ == ToolchainSocketState::UNINITED) { + return; + } + socketState_ = ToolchainSocketState::UNINITED; + close(client_); + client_ = -1; +} + +bool ToolchainWebsocket::SetWebSocketTimeOut(int32_t fd, uint32_t timeoutLimit) +{ + if (timeoutLimit > 0) { + struct timeval timeout = {timeoutLimit, 0}; + if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, + reinterpret_cast(&timeout), sizeof(timeout)) != SOCKET_SUCCESS) { + LOGE("ToolchainWebsocket:SetWebSocketTimeOut setsockopt SO_SNDTIMEO failed"); + return false; + } + if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, + reinterpret_cast(&timeout), sizeof(timeout)) != SOCKET_SUCCESS) { + LOGE("ToolchainWebsocket:SetWebSocketTimeOut setsockopt SO_RCVTIMEO failed"); + return false; + } + } + return true; +} + +bool ToolchainWebsocket::IsConnected() +{ + return socketState_ == ToolchainSocketState::CONNECTED; +} +} // namespace OHOS::ArkCompiler::Toolchain \ No newline at end of file diff --git a/tooling/client/websocket/websocket_client.h b/tooling/client/websocket/websocket_client.h index 9703852d..5c884009 100644 --- a/tooling/client/websocket/websocket_client.h +++ b/tooling/client/websocket/websocket_client.h @@ -12,3 +12,69 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#ifndef ECMASCRIPT_TOOLING_CLIENT_WEBSOCKET_CLIENT_H +#define ECMASCRIPT_TOOLING_CLIENT_WEBSOCKET_CLIENT_H + +#include +#include +#include + +#include "websocket.h" + +namespace OHOS::ArkCompiler::Toolchain { +struct ToolchainWebSocketFrame { + uint8_t fin = 0; + uint8_t opcode = 0; + uint8_t mask = 0; + uint64_t payloadLen = 0; + char maskingkey[5] = {0}; + std::unique_ptr payload = nullptr; +}; +class ToolchainWebsocket : public WebSocket { +public: + enum ToolchainSocketState : uint8_t { + UNINITED, + INITED, + CONNECTED, + }; + ToolchainWebsocket() = default; + ~ToolchainWebsocket() = default; + bool InitToolchainWebSocketForPort(int port, uint32_t timeoutLimit = 5); + bool InitToolchainWebSocketForSockName(const std::string &sockName, uint32_t timeoutLimit = 0); + bool ClientSendWSUpgradeReq(); + bool ClientRecvWSUpgradeRsp(); + bool ClientSendReq(const std::string &message); + std::string Decode(); + bool HandleFrame(ToolchainWebSocketFrame& wsFrame); + bool DecodeMessage(ToolchainWebSocketFrame& wsFrame); + uint64_t NetToHostLongLong(char* buf, uint32_t len); + bool Recv(int32_t fd, char* buf, size_t totalLen, int32_t flags) const; + bool Send(int32_t fd, const char* buf, size_t totalLen, int32_t flags) const; + void Close(); + bool SetWebSocketTimeOut(int32_t fd, uint32_t timeoutLimit); + bool IsConnected(); +private: + int32_t client_ {-1}; + std::atomic socketState_ {ToolchainSocketState::UNINITED}; + static constexpr int32_t CLIENT_WEBSOCKET_UPGRADE_RSP_LEN = 129; + static constexpr char CLIENT_WEBSOCKET_UPGRADE_REQ[] = "GET / HTTP/1.1\r\n" + "Connection: Upgrade\r\n" + "Pragma: no-cache\r\n" + "Cache-Control: no-cache\r\n" + "Upgrade: websocket\r\n" + "Sec-WebSocket-Version: 13\r\n" + "Accept-Encoding: gzip, deflate, br\r\n" + "Sec-WebSocket-Key: 64b4B+s5JDlgkdg7NekJ+g==\r\n" + "Sec-WebSocket-Extensions: permessage-deflate\r\n"; + static constexpr int32_t SOCKET_SUCCESS = 0; + static constexpr int NET_SUCCESS = 1; + static constexpr int32_t SOCKET_MASK_LEN = 4; + static constexpr int32_t SOCKET_HEADER_LEN = 2; + static constexpr int32_t PAYLOAD_LEN = 2; + static constexpr int32_t EXTEND_PAYLOAD_LEN = 8; + static constexpr char MASK_KEY[SOCKET_MASK_LEN + 1] = "abcd"; +}; +} // namespace OHOS::ArkCompiler::Toolchain + +#endif \ No newline at end of file -- Gitee