openjdk-17/Enable-TLS-to-communciation-between-JBooster-Server-.patch

2691 lines
124 KiB
Diff
Raw Normal View History

2025-02-21 11:29:09 +08:00
From 0e8fec37da9cf57066d72798633fe1fd31481ece Mon Sep 17 00:00:00 2001
Subject: Enable TLS to communciation between JBooster Server and Client JVM
---
.../linux/jbooster/net/clientStream_linux.cpp | 54 ++++
.../net/serverListeningThread_linux.cpp | 64 ++++-
src/hotspot/share/cds/filemap.cpp | 2 +-
src/hotspot/share/include/jvm.h | 5 +-
.../jbooster/client/clientDataManager.cpp | 79 +++---
.../jbooster/client/clientDataManager.hpp | 16 +-
.../jbooster/client/clientMessageHandler.cpp | 6 +-
.../share/jbooster/jBoosterManager.cpp | 1 +
.../share/jbooster/jBoosterSymbols.hpp | 1 +
.../share/jbooster/jClientArguments.cpp | 36 +--
.../share/jbooster/jClientArguments.hpp | 32 ++-
src/hotspot/share/jbooster/jClientVMFlags.cpp | 19 +-
src/hotspot/share/jbooster/jClientVMFlags.hpp | 11 +-
.../share/jbooster/jbooster_globals.hpp | 3 +
.../share/jbooster/net/clientStream.cpp | 48 +++-
.../share/jbooster/net/clientStream.hpp | 6 +
.../jbooster/net/communicationStream.cpp | 37 ++-
.../jbooster/net/communicationStream.hpp | 12 +-
src/hotspot/share/jbooster/net/errorCode.hpp | 1 +
.../jbooster/net/serverListeningThread.cpp | 55 ++++-
.../jbooster/net/serverListeningThread.hpp | 13 +-
.../share/jbooster/net/serverStream.cpp | 31 +--
.../share/jbooster/net/serverStream.hpp | 6 +-
src/hotspot/share/jbooster/net/sslUtils.cpp | 231 ++++++++++++++++++
src/hotspot/share/jbooster/net/sslUtils.hpp | 148 +++++++++++
.../jbooster/server/serverDataManager.cpp | 42 ++--
.../jbooster/server/serverDataManager.hpp | 30 ++-
.../jbooster/server/serverDataManagerLog.cpp | 17 +-
.../jbooster/server/serverMessageHandler.cpp | 30 ++-
src/hotspot/share/prims/jvm.cpp | 16 +-
src/hotspot/share/runtime/java.cpp | 2 +-
.../share/classes/jdk/jbooster/JBooster.java | 11 +-
.../share/classes/jdk/jbooster/Options.java | 22 ++
.../share/native/libjbooster/JBooster.c | 8 +-
test/jdk/tools/jbooster/JBoosterCmdTest.java | 2 +-
test/jdk/tools/jbooster/JBoosterNetTest.java | 2 +-
test/jdk/tools/jbooster/JBoosterSSLTest.java | 152 ++++++++++++
.../jbooster/JBoosterSharedCacheTest.java | 150 ++++++++++++
test/jdk/tools/jbooster/JBoosterTestBase.java | 6 +-
test/jdk/tools/jbooster/server-cert.pem | 22 ++
test/jdk/tools/jbooster/server-key.pem | 27 ++
test/jdk/tools/jbooster/unrelated-cert.pem | 22 ++
42 files changed, 1243 insertions(+), 235 deletions(-)
create mode 100644 src/hotspot/share/jbooster/net/sslUtils.cpp
create mode 100644 src/hotspot/share/jbooster/net/sslUtils.hpp
create mode 100644 test/jdk/tools/jbooster/JBoosterSSLTest.java
create mode 100644 test/jdk/tools/jbooster/JBoosterSharedCacheTest.java
create mode 100644 test/jdk/tools/jbooster/server-cert.pem
create mode 100644 test/jdk/tools/jbooster/server-key.pem
create mode 100644 test/jdk/tools/jbooster/unrelated-cert.pem
diff --git a/src/hotspot/os/linux/jbooster/net/clientStream_linux.cpp b/src/hotspot/os/linux/jbooster/net/clientStream_linux.cpp
index 6425ef0f2..d0b43506d 100644
--- a/src/hotspot/os/linux/jbooster/net/clientStream_linux.cpp
+++ b/src/hotspot/os/linux/jbooster/net/clientStream_linux.cpp
@@ -28,7 +28,9 @@
#include "jbooster/net/clientStream.hpp"
#include "jbooster/net/errorCode.hpp"
+#include "jbooster/net/sslUtils.hpp"
#include "logging/log.hpp"
+#include "runtime/java.hpp"
#include "runtime/os.hpp"
#define LOG_INNER(socket_fd, address, port, err_code, format, args...) \
@@ -142,3 +144,55 @@ int ClientStream::try_to_connect_once(int* res_fd, const char* address, const ch
*res_fd = -1;
return res_err;
}
+
+int ClientStream::try_to_ssl_connect(SSL** res_ssl, int conn_fd) {
+ errno = 0;
+
+ SSL* ssl = nullptr;
+ do {
+ SSL* ssl = SSLUtils::ssl_new(_client_ssl_ctx);
+ if (ssl == nullptr) {
+ log_error(jbooster, rpc)("Failed to get SSL.");
+ break;
+ }
+
+ int ret = 0;
+ if (ret = SSLUtils::ssl_set_fd(ssl, conn_fd) != 1) {
+ SSLUtils::handle_ssl_error(ssl, ret, "Failed to set SSL file descriptor");
+ break;
+ }
+
+ if (ret = SSLUtils::ssl_connect(ssl) != 1) {
+ SSLUtils::handle_ssl_error(ssl, ret, "Failed to build SSL connection");
+ break;
+ }
+
+ if (!verify_cert(ssl)) {
+ break;
+ }
+
+ // success
+ assert(errno == 0, "why errno=%s", JBErr::err_name(errno));
+ *res_ssl = ssl;
+ return 0;
+ } while (false);
+
+ // fail
+ int res_err = JBErr::BAD_SSL;
+ SSLUtils::shutdown_and_free_ssl(ssl);
+ return res_err;
+}
+
+bool ClientStream::verify_cert(SSL* ssl) {
+ X509* cert = SSLUtils::ssl_get_peer_certificate(ssl);
+ if ((cert == nullptr)) {
+ log_error(jbooster, rpc)("Server cert unspecified.");
+ return false;
+ }
+ int res = SSLUtils::ssl_get_verify_result(ssl);
+ if (res != X509_V_OK) {
+ log_error(jbooster, rpc)("Failed to verify server cert.");
+ return false;
+ }
+ return true;
+}
diff --git a/src/hotspot/os/linux/jbooster/net/serverListeningThread_linux.cpp b/src/hotspot/os/linux/jbooster/net/serverListeningThread_linux.cpp
index bc3eae5b0..073052e72 100644
--- a/src/hotspot/os/linux/jbooster/net/serverListeningThread_linux.cpp
+++ b/src/hotspot/os/linux/jbooster/net/serverListeningThread_linux.cpp
@@ -28,8 +28,10 @@
#include "jbooster/net/errorCode.hpp"
#include "jbooster/net/serverListeningThread.hpp"
+#include "jbooster/net/sslUtils.hpp"
#include "logging/log.hpp"
#include "runtime/interfaceSupport.inline.hpp"
+#include "runtime/java.hpp"
static int init_server_socket_opts(int socket_fd) {
// enable reuse of address
@@ -105,6 +107,56 @@ static int bind_address(const char* address, uint16_t port) {
return socket_fd;
}
+static SSL* try_to_ssl_connect(int conn_fd, SSL_CTX* ssl_ctx) {
+ SSL* ssl = SSLUtils::ssl_new(ssl_ctx);
+ if (ssl == nullptr) {
+ log_error(jbooster, rpc)("Failed to get SSL.");
+ os::close(conn_fd);
+ return nullptr;
+ }
+
+ int ret = 0;
+ const char* error_description = nullptr;
+ if (ret = SSLUtils::ssl_set_fd(ssl, conn_fd) != 1) {
+ error_description = "Failed to set SSL file descriptor";
+ } else if (ret = SSLUtils::ssl_accept(ssl) != 1) {
+ error_description = "Failed to accept SSL connection";
+ }
+
+ if (error_description != nullptr) {
+ SSLUtils::handle_ssl_error(ssl, ret, error_description);
+ SSLUtils::shutdown_and_free_ssl(ssl);
+ os::close(conn_fd);
+ return nullptr;
+ }
+
+ log_info(jbooster, rpc)("Succeeded to build SSL connection.");
+ return ssl;
+}
+
+bool ServerListeningThread::prepare_and_handle_new_connection(int server_fd, sockaddr_in* acc_addr, socklen_t* acc_addrlen, TRAPS) {
+ int conn_fd = accept(server_fd, (sockaddr*)acc_addr, acc_addrlen);
+ if (conn_fd < 0) {
+ if (errno != EAGAIN && errno != EWOULDBLOCK) {
+ log_error(jbooster, rpc)("Failed to accept: %s.", strerror(errno));
+ }
+ return false;
+ }
+ if (init_accepted_socket_opts(conn_fd, _timeout_ms) < 0) {
+ return false;
+ }
+
+ SSL* ssl = nullptr;
+ if (_server_ssl_ctx != nullptr) {
+ ssl = try_to_ssl_connect(conn_fd, _server_ssl_ctx);
+ if (ssl == nullptr) {
+ return false;
+ }
+ }
+ handle_new_connection(conn_fd, ssl, THREAD);
+ return true;
+}
+
/**
* Keep listening for client requests.
*/
@@ -138,19 +190,15 @@ int ServerListeningThread::run_listener(TRAPS) {
}
while (!get_exit_flag()) {
- int conn_fd = accept(server_fd, (sockaddr*)&acc_addr, &acc_addrlen);
- if (conn_fd < 0) {
- if (errno != EAGAIN && errno != EWOULDBLOCK) {
- log_error(jbooster, rpc)("Failed to accept: %s.", strerror(errno));
- }
+ if (!prepare_and_handle_new_connection(server_fd, &acc_addr, &acc_addrlen, THREAD)) {
break;
}
- if (init_accepted_socket_opts(conn_fd, _timeout_ms) < 0) break;
-
- handle_new_connection(conn_fd, THREAD);
}
}
+ if (_server_ssl_ctx != nullptr) {
+ SSLUtils::ssl_ctx_free(_server_ssl_ctx);
+ }
close(server_fd);
log_debug(jbooster, rpc)("The JBooster server listener thread stopped.");
return 0;
diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp
index 1fe0adbe5..76e078d12 100644
--- a/src/hotspot/share/cds/filemap.cpp
+++ b/src/hotspot/share/cds/filemap.cpp
@@ -1216,7 +1216,7 @@ void FileMapInfo::open_for_write(const char* path) {
int fd;
#if INCLUDE_JBOOSTER
- if (UseJBooster && ClientDataManager::get().is_cds_allowed()) {
+ if (UseJBooster && ClientDataManager::get().boost_level().is_cds_allowed()) {
// The _full_path points to the tmp file in the JBooster environment.
// The tmp file should have been created before (see dump_cds() in
// clientMessageHandler.cpp). So do not remove it or try to create it.
diff --git a/src/hotspot/share/include/jvm.h b/src/hotspot/share/include/jvm.h
index 488ad25ce..7c917a240 100644
--- a/src/hotspot/share/include/jvm.h
+++ b/src/hotspot/share/include/jvm.h
@@ -1105,13 +1105,14 @@ JVM_GetEnclosingMethodInfo(JNIEnv* env, jclass ofClass);
* Init the JBooster server in Hotspot.
*/
JNIEXPORT void JNICALL
-JVM_JBoosterInitVM(JNIEnv *env, jint server_port, jint connection_timeout, jint cleanup_timeout, jstring cache_path);
+JVM_JBoosterInitVM(JNIEnv *env, jint server_port, jint connection_timeout, jint cleanup_timeout,
+ jstring cache_path, jstring ssl_key, jstring ssl_cert);
/**
* Handle a TCP connection.
*/
JNIEXPORT void JNICALL
-JVM_JBoosterHandleConnection(JNIEnv *env, jint connection_fd);
+JVM_JBoosterHandleConnection(JNIEnv *env, jint connection_fd, jlong connection_ssl);
/**
* Print data in ServerDataManager.
diff --git a/src/hotspot/share/jbooster/client/clientDataManager.cpp b/src/hotspot/share/jbooster/client/clientDataManager.cpp
index 0504dc656..3fbe143a8 100644
--- a/src/hotspot/share/jbooster/client/clientDataManager.cpp
+++ b/src/hotspot/share/jbooster/client/clientDataManager.cpp
@@ -27,6 +27,7 @@
#include "jbooster/client/clientDataManager.hpp"
#include "jbooster/client/clientStartupSignal.hpp"
#include "jbooster/net/clientStream.hpp"
+#include "jbooster/net/sslUtils.hpp"
#include "logging/log.hpp"
#include "runtime/arguments.hpp"
#include "runtime/globals_extension.hpp"
@@ -43,15 +44,9 @@ ClientDataManager::ClientDataManager() {
_program_str_id = nullptr;
_cache_dir_path = nullptr;
- _allow_aot = false;
- _allow_cds = false;
- _allow_clr = false;
- _allow_pgo = false;
-
_using_aot = false;
_using_cds = false;
_using_clr = false;
- _using_pgo = false;
_cache_clr_path = nullptr;
_cache_cds_path = nullptr;
@@ -81,25 +76,32 @@ void ClientDataManager::init_client_vm_options() {
if (!FLAG_IS_DEFAULT(UseBoostPackages)) {
if (strcmp(UseBoostPackages, "all") == 0) {
- _allow_clr = _allow_cds = _allow_aot = _allow_pgo = true;
+ _boost_level.set_allow_clr(true);
+ _boost_level.set_allow_cds(true);
+ _boost_level.set_allow_aot(true);
+ _boost_level.set_enable_aot_pgo(true);
} else {
- _allow_clr = is_option_on("UseBoostPackages", UseBoostPackages, "clr");
- _allow_cds = is_option_on("UseBoostPackages", UseBoostPackages, "cds");
- _allow_aot = is_option_on("UseBoostPackages", UseBoostPackages, "aot");
- _allow_pgo = is_option_on("UseBoostPackages", UseBoostPackages, "pgo");
- if (_allow_pgo) _allow_aot = true;
+ _boost_level.set_allow_clr(is_option_on("UseBoostPackages", UseBoostPackages, "clr"));
+ _boost_level.set_allow_cds(is_option_on("UseBoostPackages", UseBoostPackages, "cds"));
+ _boost_level.set_allow_aot(is_option_on("UseBoostPackages", UseBoostPackages, "aot"));
+ _boost_level.set_enable_aot_pgo(is_option_on("UseBoostPackages", UseBoostPackages, "pgo"));
+ if (_boost_level.is_aot_pgo_enabled()) _boost_level.set_allow_aot(true);
}
} else {
switch (BoostStopAtLevel) {
- case 4: _allow_pgo = true;
- case 3: _allow_aot = true;
- case 2: _allow_cds = true;
- case 1: _allow_clr = true;
+ case 4: _boost_level.set_enable_aot_pgo(true);
+ case 3: _boost_level.set_allow_aot(true);
+ case 2: _boost_level.set_allow_cds(true);
+ case 1: _boost_level.set_allow_clr(true);
case 0: break;
default: break;
}
}
+ if (FLAG_IS_DEFAULT(UseAggressiveCDS) || UseAggressiveCDS) {
+ _boost_level.set_enable_cds_agg(true);
+ }
+
if (JBoosterStartupSignal != nullptr) {
ClientStartupSignal::init_phase1();
}
@@ -113,17 +115,23 @@ void ClientDataManager::init_const() {
_program_args->is_jar(),
_program_args->hash());
_cache_clr_path = JBoosterManager::calc_cache_path(_cache_dir_path, _program_str_id, "clr.log");
- _cache_cds_path = JBoosterManager::calc_cache_path(_cache_dir_path, _program_str_id, "cds.jsa");
- const char* aot_path_suffix = _allow_pgo ? "aot-pgo.so" : "aot.so";
+ const char* cds_path_suffix = _boost_level.is_cds_agg_enabled() ? "cds-agg.jsa" : "cds-dy.jsa";
+ _cache_cds_path = JBoosterManager::calc_cache_path(_cache_dir_path, _program_str_id, cds_path_suffix);
+ const char* aot_path_suffix = _boost_level.is_aot_pgo_enabled() ? "aot-pgo.so" : "aot-static.so";
_cache_aot_path = JBoosterManager::calc_cache_path(_cache_dir_path, _program_str_id, aot_path_suffix);
}
void ClientDataManager::init_client_duty() {
+ if (JBoosterServerSSLRootCerts) {
+ if (!SSLUtils::init_ssl_lib()) {
+ vm_exit_during_initialization("Failed to load all functions from OpenSSL Dynamic Library.");
+ }
+ ClientStream::client_init_ssl_ctx(JBoosterServerSSLRootCerts);
+ }
// Connect to jbooster before initializing CDS, before loading java_lang_classes
// and before starting the compiler threads.
ClientStream client_stream(JBoosterAddress, JBoosterPort, JBoosterTimeout, nullptr);
int rpc_err = client_stream.connect_and_init_session(&_using_clr, &_using_cds, &_using_aot);
- if (_using_aot && _allow_pgo) _using_pgo = true;
set_server_available(rpc_err == 0);
}
@@ -132,11 +140,10 @@ void ClientDataManager::init_client_duty_under_local_mode() {
_using_clr = FileUtils::is_file(_cache_clr_path);
_using_cds = FileUtils::is_file(_cache_cds_path);
_using_aot = FileUtils::is_file(_cache_aot_path);
- if (_using_aot && _allow_pgo) _using_pgo = true;
}
jint ClientDataManager::init_clr_options() {
- if (!is_clr_allowed()) return JNI_OK;
+ if (!_boost_level.is_clr_allowed()) return JNI_OK;
if (FLAG_SET_CMDLINE(UseClassLoaderResourceCache, true) != JVMFlag::SUCCESS) {
return JNI_EINVAL;
@@ -156,10 +163,14 @@ jint ClientDataManager::init_clr_options() {
}
jint ClientDataManager::init_cds_options() {
- if (!is_cds_allowed()) return JNI_OK;
+ if (!_boost_level.is_cds_allowed()) return JNI_OK;
+
+ if (FLAG_IS_CMDLINE(SharedArchiveFile) || FLAG_IS_CMDLINE(ArchiveClassesAtExit) || FLAG_IS_CMDLINE(SharedArchiveConfigFile)) {
+ vm_exit_during_initialization("Do not set CDS path manually whe using JBooster.");
+ }
- if (FLAG_IS_CMDLINE(SharedArchiveFile) || FLAG_IS_CMDLINE(ArchiveClassesAtExit)) {
- vm_exit_during_initialization("Do not set CDS manually whe using JBooster.");
+ if (FLAG_IS_CMDLINE(DynamicDumpSharedSpaces) || FLAG_IS_CMDLINE(DumpSharedSpaces) || FLAG_IS_CMDLINE(UseSharedSpaces)) {
+ vm_exit_during_initialization("Do not set dump/load CDS manually whe using JBooster.");
}
if (is_cds_being_used()) {
@@ -197,7 +208,7 @@ jint ClientDataManager::init_cds_options() {
}
jint ClientDataManager::init_aot_options() {
- if (!is_aot_allowed()) return JNI_OK;
+ if (!_boost_level.is_aot_allowed()) return JNI_OK;
if (FLAG_SET_CMDLINE(UseAOT, true) != JVMFlag::SUCCESS) {
return JNI_EINVAL;
}
@@ -210,7 +221,7 @@ jint ClientDataManager::init_aot_options() {
}
jint ClientDataManager::init_pgo_options() {
- if (!is_pgo_allowed()) return JNI_OK;
+ if (!_boost_level.is_aot_pgo_enabled()) return JNI_OK;
if (FLAG_SET_CMDLINE(TypeProfileWidth, 8) != JVMFlag::SUCCESS) {
return JNI_EINVAL;
}
@@ -220,13 +231,11 @@ jint ClientDataManager::init_pgo_options() {
void ClientDataManager::print_init_state() {
log_info(jbooster)("Using boost packages:\n"
" - CLR: allowed_to_use=%s,\tis_being_used=%s\n"
- " - CDS: allowed_to_use=%s,\tis_being_used=%s\n"
- " - AOT: allowed_to_use=%s,\tis_being_used=%s\n"
- " - PGO: allowed_to_use=%s,\tis_being_used=%s",
- BOOL_TO_STR(is_clr_allowed()), BOOL_TO_STR(is_clr_being_used()),
- BOOL_TO_STR(is_cds_allowed()), BOOL_TO_STR(is_cds_being_used()),
- BOOL_TO_STR(is_aot_allowed()), BOOL_TO_STR(is_aot_being_used()),
- BOOL_TO_STR(is_pgo_allowed()), BOOL_TO_STR(is_pgo_being_used()));
+ " - CDS: allowed_to_use=%s,\tis_being_used=%s,\tis_aggressive_cds_enabled=%s\n"
+ " - AOT: allowed_to_use=%s,\tis_being_used=%s,\tis_pgo_aot_enabled=%s\n",
+ BOOL_TO_STR(_boost_level.is_clr_allowed()), BOOL_TO_STR(is_clr_being_used()),
+ BOOL_TO_STR(_boost_level.is_cds_allowed()), BOOL_TO_STR(is_cds_being_used()), BOOL_TO_STR(_boost_level.is_cds_agg_enabled()),
+ BOOL_TO_STR(_boost_level.is_aot_allowed()), BOOL_TO_STR(is_aot_being_used()), BOOL_TO_STR(_boost_level.is_aot_pgo_enabled()));
}
static void check_jbooster_port() {
@@ -328,7 +337,7 @@ void ClientDataManager::init_phase2(TRAPS) {
}
ClientDaemonThread::start_thread(CHECK);
- if (_singleton->is_clr_allowed()) {
+ if (_singleton->_boost_level.is_clr_allowed()) {
Klass* klass = SystemDictionary::resolve_or_fail(vmSymbols::java_net_ClassLoaderResourceCache(), true, CHECK);
InstanceKlass::cast(klass)->initialize(CHECK);
}
@@ -339,7 +348,7 @@ jint ClientDataManager::escape() {
return JNI_EINVAL;
}
- if(!JBoosterLocalMode){
+ if (!JBoosterLocalMode) {
log_error(jbooster)("Rolled back to the original path (UseJBooster=false), since the server is unavailable.");
}
return JNI_OK;
diff --git a/src/hotspot/share/jbooster/client/clientDataManager.hpp b/src/hotspot/share/jbooster/client/clientDataManager.hpp
index 07be0dc2a..da4a8cacb 100644
--- a/src/hotspot/share/jbooster/client/clientDataManager.hpp
+++ b/src/hotspot/share/jbooster/client/clientDataManager.hpp
@@ -39,15 +39,11 @@ class ClientDataManager: public CHeapObj<mtJBooster> {
const char* _program_str_id;
const char* _cache_dir_path;
- bool _allow_clr;
- bool _allow_cds;
- bool _allow_aot;
- bool _allow_pgo;
+ JClientBoostLevel _boost_level;
bool _using_clr;
bool _using_cds;
bool _using_aot;
- bool _using_pgo;
const char* _cache_clr_path;
const char* _cache_cds_path;
@@ -102,21 +98,17 @@ public:
// $HOME/.jbooster/client
const char* cache_dir_path() { return _cache_dir_path; }
- bool is_clr_allowed() { return _allow_clr; }
- bool is_cds_allowed() { return _allow_cds; }
- bool is_aot_allowed() { return _allow_aot; }
- bool is_pgo_allowed() { return _allow_pgo; }
+ JClientBoostLevel& boost_level() { return _boost_level; }
bool is_clr_being_used() { return _using_clr; }
bool is_cds_being_used() { return _using_cds; }
bool is_aot_being_used() { return _using_aot; }
- bool is_pgo_being_used() { return _using_pgo; }
// <cache_dir>/client/cache-<parogram_str_id>-clr.log
const char* cache_clr_path() { return _cache_clr_path; }
- // <cache_dir>/client/cache-<parogram_str_id>-cds.jsa
+ // <cache_dir>/client/cache-<parogram_str_id>-cds-[dy|agg].jsa
const char* cache_cds_path() { return _cache_cds_path; }
- // <cache_dir>/client/cache-<parogram_str_id>-aot[-pgo].so
+ // <cache_dir>/client/cache-<parogram_str_id>-aot-[static|pgo].so
const char* cache_aot_path() { return _cache_aot_path; }
uint32_t session_id() { return _session_id; }
diff --git a/src/hotspot/share/jbooster/client/clientMessageHandler.cpp b/src/hotspot/share/jbooster/client/clientMessageHandler.cpp
index 0ebe350a0..9119b897a 100644
--- a/src/hotspot/share/jbooster/client/clientMessageHandler.cpp
+++ b/src/hotspot/share/jbooster/client/clientMessageHandler.cpp
@@ -87,7 +87,7 @@ void ClientMessageHandler::trigger_cache_generation_tasks(TriggerTaskPhase phase
ClientMessageHandler msg_handler(client_stream);
bool cache_file_task = false;
- if (ClientDataManager::get().is_clr_allowed() || ClientDataManager::get().is_cds_allowed()) {
+ if (ClientDataManager::get().boost_level().is_clr_allowed() || ClientDataManager::get().boost_level().is_cds_allowed()) {
cache_file_task = (phase == ON_SHUTDOWN);
}
if (cache_file_task) {
@@ -95,7 +95,7 @@ void ClientMessageHandler::trigger_cache_generation_tasks(TriggerTaskPhase phase
}
bool lazy_aot_task = false;
- if (ClientDataManager::get().is_aot_allowed()) {
+ if (ClientDataManager::get().boost_level().is_aot_allowed()) {
lazy_aot_task = ((phase == ON_STARTUP) || ((phase == ON_SHUTDOWN) && !ClientDataManager::get().is_startup_end()));
}
if (lazy_aot_task) {
@@ -170,7 +170,7 @@ static void dump_cds() {
}
int ClientMessageHandler::handle_CacheAggressiveCDS() {
- if (DynamicDumpSharedSpaces && ClientDataManager::get().is_cds_allowed()) {
+ if (DynamicDumpSharedSpaces && ClientDataManager::get().boost_level().is_cds_allowed()) {
dump_cds();
}
FileWrapper file(ClientDataManager::get().cache_cds_path(),
diff --git a/src/hotspot/share/jbooster/jBoosterManager.cpp b/src/hotspot/share/jbooster/jBoosterManager.cpp
index 64af5e894..2a8995f4a 100644
--- a/src/hotspot/share/jbooster/jBoosterManager.cpp
+++ b/src/hotspot/share/jbooster/jBoosterManager.cpp
@@ -178,4 +178,5 @@ void JBoosterManager::check_arguments() {
check_argument(FLAG_MEMBER_ENUM(JBoosterClientStrictMatch));
check_argument(FLAG_MEMBER_ENUM(PrintAllClassInfo));
check_argument(FLAG_MEMBER_ENUM(CheckClassFileTimeStamp));
+ check_argument(FLAG_MEMBER_ENUM(JBoosterServerSSLRootCerts));
}
\ No newline at end of file
diff --git a/src/hotspot/share/jbooster/jBoosterSymbols.hpp b/src/hotspot/share/jbooster/jBoosterSymbols.hpp
index e45bf85aa..4d7f64318 100644
--- a/src/hotspot/share/jbooster/jBoosterSymbols.hpp
+++ b/src/hotspot/share/jbooster/jBoosterSymbols.hpp
@@ -26,6 +26,7 @@
#define JBOOSTER_TEMPLATES(template) \
template(receiveConnection_name, "receiveConnection") \
+ template(receiveConnection_signature, "(IJ)Z") \
template(codesource_signature, "Ljava/security/CodeSource;") \
template(getProtectionDomainByURLString_name, "getProtectionDomainByURLString") \
template(getProtectionDomainByURLString_signature, "(Ljava/lang/String;)Ljava/security/ProtectionDomain;") \
diff --git a/src/hotspot/share/jbooster/jClientArguments.cpp b/src/hotspot/share/jbooster/jClientArguments.cpp
index 1ae91674f..37093d031 100644
--- a/src/hotspot/share/jbooster/jClientArguments.cpp
+++ b/src/hotspot/share/jbooster/jClientArguments.cpp
@@ -209,10 +209,6 @@ void JClientArguments::init_for_client() {
} else {
_java_commands = StringUtils::copy_to_heap("<ignored>", mtJBooster);
}
- _jbooster_allow_clr = ClientDataManager::get().is_clr_allowed();
- _jbooster_allow_cds = ClientDataManager::get().is_cds_allowed();
- _jbooster_allow_aot = ClientDataManager::get().is_aot_allowed();
- _jbooster_allow_pgo = ClientDataManager::get().is_pgo_allowed();
_related_flags = new JClientVMFlags(true);
_hash = calc_hash();
@@ -232,11 +228,7 @@ uint32_t JClientArguments::calc_hash() {
result = calc_new_hash(result, _classpath_timestamp_hash);
result = calc_new_hash(result, _agent_name_hash);
result = calc_new_hash(result, StringUtils::hash_code(_java_commands));
- result = calc_new_hash(result, primitive_hash(_jbooster_allow_clr));
- result = calc_new_hash(result, primitive_hash(_jbooster_allow_cds));
- result = calc_new_hash(result, primitive_hash(_jbooster_allow_aot));
- result = calc_new_hash(result, primitive_hash(_jbooster_allow_pgo));
- result = calc_new_hash(result, _related_flags->hash(_jbooster_allow_clr, _jbooster_allow_cds, _jbooster_allow_aot));
+ result = calc_new_hash(result, _related_flags->hash());
return result;
}
@@ -255,14 +247,7 @@ bool JClientArguments::equals(const JClientArguments* that) const {
if (this->_classpath_timestamp_hash != that->_classpath_timestamp_hash) return false;
if (this->_agent_name_hash != that->_agent_name_hash) return false;
if (StringUtils::compare(this->_java_commands, that->_java_commands) != 0) return false;
- if (this->_jbooster_allow_clr != that->_jbooster_allow_clr) return false;
- if (this->_jbooster_allow_cds != that->_jbooster_allow_cds) return false;
- if (this->_jbooster_allow_aot != that->_jbooster_allow_aot) return false;
- if (this->_jbooster_allow_pgo != that->_jbooster_allow_pgo) return false;
- if (!this->_related_flags->equals(that->_related_flags,
- _jbooster_allow_clr,
- _jbooster_allow_cds,
- _jbooster_allow_aot)) return false;
+ if (!this->_related_flags->equals(that->_related_flags)) return false;
return true;
}
@@ -279,14 +264,8 @@ void JClientArguments::print_args(outputStream* st) const {
st->print_cr(" classpath_timestamp_hash: %x", _classpath_timestamp_hash);
st->print_cr(" agent_name_hash: %x", _agent_name_hash);
st->print_cr(" java_commands: \"%s\"", _java_commands);
- st->print_cr(" allow_clr: %s", BOOL_TO_STR(_jbooster_allow_clr));
- st->print_cr(" allow_cds: %s", BOOL_TO_STR(_jbooster_allow_cds));
- st->print_cr(" allow_aot: %s", BOOL_TO_STR(_jbooster_allow_aot));
- st->print_cr(" allow_pgo: %s", BOOL_TO_STR(_jbooster_allow_pgo));
st->print_cr(" vm_flags:");
- st->print_cr(" hash: %u", _related_flags->hash(_jbooster_allow_clr,
- _jbooster_allow_cds,
- _jbooster_allow_aot));
+ st->print_cr(" hash: %u", _related_flags->hash());
_related_flags->print_flags(st);
}
@@ -308,10 +287,6 @@ int JClientArguments::serialize(MessageBuffer& buf) const {
JB_RETURN(buf.serialize_no_meta(_classpath_timestamp_hash));
JB_RETURN(buf.serialize_no_meta(_agent_name_hash));
JB_RETURN(buf.serialize_with_meta(&_java_commands));
- JB_RETURN(buf.serialize_no_meta(_jbooster_allow_clr));
- JB_RETURN(buf.serialize_no_meta(_jbooster_allow_cds));
- JB_RETURN(buf.serialize_no_meta(_jbooster_allow_aot));
- JB_RETURN(buf.serialize_no_meta(_jbooster_allow_pgo));
JB_RETURN(buf.serialize_with_meta(_related_flags));
JB_RETURN(buf.serialize_no_meta(_hash));
@@ -351,11 +326,6 @@ int JClientArguments::deserialize(MessageBuffer& buf) {
JB_RETURN(buf.deserialize_with_meta(&sw_java_commands));
_java_commands = sw_java_commands.export_string();
- JB_RETURN(buf.deserialize_ref_no_meta(_jbooster_allow_clr));
- JB_RETURN(buf.deserialize_ref_no_meta(_jbooster_allow_cds));
- JB_RETURN(buf.deserialize_ref_no_meta(_jbooster_allow_aot));
- JB_RETURN(buf.deserialize_ref_no_meta(_jbooster_allow_pgo));
-
_related_flags = new JClientVMFlags(false);
JB_RETURN(buf.deserialize_with_meta(_related_flags));
diff --git a/src/hotspot/share/jbooster/jClientArguments.hpp b/src/hotspot/share/jbooster/jClientArguments.hpp
index 7a0db1738..be057a07d 100644
--- a/src/hotspot/share/jbooster/jClientArguments.hpp
+++ b/src/hotspot/share/jbooster/jClientArguments.hpp
@@ -27,6 +27,30 @@
#include "jbooster/jClientVMFlags.hpp"
#include "jbooster/net/serialization.hpp"
+class JClientBoostLevel {
+ bool _allow_clr;
+ bool _allow_cds;
+ bool _allow_aot;
+ bool _enable_aot_pgo;
+ bool _enable_cds_agg;
+
+public:
+ JClientBoostLevel(): _allow_clr(false), _allow_cds(false), _allow_aot(false), _enable_aot_pgo(false), _enable_cds_agg(false) {}
+ JClientBoostLevel(const JClientBoostLevel& level) = default;
+
+ bool is_clr_allowed() const { return _allow_clr; }
+ bool is_cds_allowed() const { return _allow_cds; }
+ bool is_aot_allowed() const { return _allow_aot; }
+ bool is_aot_pgo_enabled() const {return _enable_aot_pgo; }
+ bool is_cds_agg_enabled() const {return _enable_cds_agg; }
+
+ void set_allow_clr(bool allow_clr) { _allow_clr = allow_clr; }
+ void set_allow_cds(bool allow_cds) { _allow_cds = allow_cds; }
+ void set_allow_aot(bool allow_aot) { _allow_aot = allow_aot; }
+ void set_enable_aot_pgo(bool enable_aot_pgo) { _enable_aot_pgo = enable_aot_pgo; }
+ void set_enable_cds_agg(bool enable_cds_agg) { _enable_cds_agg = enable_cds_agg; }
+};
+
/**
* Arguments that identify a program.
*/
@@ -64,10 +88,6 @@ private:
uint32_t _classpath_timestamp_hash;
uint32_t _agent_name_hash;
const char* _java_commands;
- bool _jbooster_allow_clr;
- bool _jbooster_allow_cds;
- bool _jbooster_allow_aot;
- bool _jbooster_allow_pgo;
JClientVMFlags* _related_flags;
// ========================= end =========================
@@ -93,10 +113,6 @@ public:
uint32_t classpath_timestamp_hash() const { return _classpath_timestamp_hash; }
uint32_t agent_name_hash() const { return _agent_name_hash; }
const char* java_commands() const { return _java_commands; }
- bool jbooster_allow_clr() const { return _jbooster_allow_clr; }
- bool jbooster_allow_cds() const { return _jbooster_allow_cds; }
- bool jbooster_allow_aot() const { return _jbooster_allow_aot; }
- bool jbooster_allow_pgo() const { return _jbooster_allow_pgo; }
JClientVMFlags* related_flags() const { return _related_flags; }
bool equals(const JClientArguments* that) const;
diff --git a/src/hotspot/share/jbooster/jClientVMFlags.cpp b/src/hotspot/share/jbooster/jClientVMFlags.cpp
index 6e46aeb48..570c1b64c 100644
--- a/src/hotspot/share/jbooster/jClientVMFlags.cpp
+++ b/src/hotspot/share/jbooster/jClientVMFlags.cpp
@@ -125,28 +125,17 @@ JClientVMFlags::~JClientVMFlags() {
#undef FREE_FLAG
}
-bool JClientVMFlags::equals(JClientVMFlags* that, bool allow_clr, bool allow_cds, bool allow_aot) {
+bool JClientVMFlags::equals(JClientVMFlags* that) {
#define CMP_FLAG(type, flag) if (!FlagTypeHandler<type>::equals(this->v_##flag, that->v_##flag)) return false;
- if (allow_cds) {
- JCLIENT_CDS_VM_FLAGS(CMP_FLAG)
- }
- if (allow_aot) {
- JCLIENT_AOT_VM_FLAGS(CMP_FLAG)
- }
+ JCLIENT_VM_FLAGS(CMP_FLAG)
#undef CMP_FLAG
-
return true;
}
-uint32_t JClientVMFlags::hash(bool allow_clr, bool allow_cds, bool allow_aot) {
+uint32_t JClientVMFlags::hash() {
uint32_t result = 1;
#define CALC_FLAG_HASH(type, flag) result = 31 * result + FlagTypeHandler<type>::hash(v_##flag);
- if (allow_cds) {
- JCLIENT_CDS_VM_FLAGS(CALC_FLAG_HASH)
- }
- if (allow_aot) {
- JCLIENT_AOT_VM_FLAGS(CALC_FLAG_HASH)
- }
+ JCLIENT_VM_FLAGS(CALC_FLAG_HASH)
#undef CALC_FLAG_HASH
return result;
}
diff --git a/src/hotspot/share/jbooster/jClientVMFlags.hpp b/src/hotspot/share/jbooster/jClientVMFlags.hpp
index 71da58934..9d203d041 100644
--- a/src/hotspot/share/jbooster/jClientVMFlags.hpp
+++ b/src/hotspot/share/jbooster/jClientVMFlags.hpp
@@ -29,14 +29,7 @@
#include "runtime/globals_extension.hpp"
#define JCLIENT_CDS_VM_FLAGS(f) \
- f(bool, DynamicDumpSharedSpaces ) \
- f(bool, DumpSharedSpaces ) \
- f(bool, UseSharedSpaces ) \
- f(ccstr, SharedArchiveFile ) \
- f(ccstr, SharedArchiveConfigFile ) \
- f(ccstr, ArchiveClassesAtExit ) \
f(size_t, MaxMetaspaceSize ) \
- f(bool, UseAggressiveCDS ) \
f(size_t, SharedBaseAddress ) \
f(bool, UseCompressedOops ) \
f(bool, UseCompressedClassPointers ) \
@@ -87,8 +80,8 @@ public:
int serialize(MessageBuffer& buf) const;
int deserialize(MessageBuffer& buf);
- bool equals(JClientVMFlags* that, bool allow_clr, bool allow_cds, bool allow_aot);
- uint32_t hash(bool allow_clr, bool allow_cds, bool allow_aot);
+ bool equals(JClientVMFlags* that);
+ uint32_t hash();
void print_flags(outputStream* st);
};
diff --git a/src/hotspot/share/jbooster/jbooster_globals.hpp b/src/hotspot/share/jbooster/jbooster_globals.hpp
index 3eb74abf8..74968af75 100644
--- a/src/hotspot/share/jbooster/jbooster_globals.hpp
+++ b/src/hotspot/share/jbooster/jbooster_globals.hpp
@@ -116,6 +116,9 @@
\
product(bool, ClassLoaderResourceCacheVerboseMode, false, DIAGNOSTIC, \
"Dump/load more data for verification and debugging.") \
+ \
+ product(ccstr, JBoosterServerSSLRootCerts, NULL, EXPERIMENTAL, \
+ "The file path to save server SSL root certificate.") \
// end of JBOOSTER_FLAGS
diff --git a/src/hotspot/share/jbooster/net/clientStream.cpp b/src/hotspot/share/jbooster/net/clientStream.cpp
index d72b796d5..5b66e083f 100644
--- a/src/hotspot/share/jbooster/net/clientStream.cpp
+++ b/src/hotspot/share/jbooster/net/clientStream.cpp
@@ -25,10 +25,13 @@
#include "jbooster/net/clientStream.hpp"
#include "jbooster/net/rpcCompatibility.hpp"
#include "jbooster/net/serializationWrappers.hpp"
+#include "jbooster/net/sslUtils.hpp"
#include "jbooster/utilities/fileUtils.hpp"
#include "runtime/java.hpp"
#include "runtime/thread.hpp"
+SSL_CTX* ClientStream::_client_ssl_ctx = nullptr;
+
ClientStream::ClientStream(const char* address, const char* port, uint32_t timeout_ms):
CommunicationStream(Thread::current_or_null()),
_server_address(address),
@@ -49,6 +52,29 @@ ClientStream::~ClientStream() {
}
}
+void ClientStream::client_init_ssl_ctx(const char* root_certs) {
+ guarantee(_client_ssl_ctx == nullptr, "sanity");
+
+ SSLUtils::openssl_init_ssl();
+ _client_ssl_ctx = SSLUtils::ssl_ctx_new(SSLUtils::sslv23_client_method());
+ if (_client_ssl_ctx == nullptr) {
+ vm_exit_during_initialization("Failed to create SSL context.");
+ }
+
+ SSLUtils::ssl_ctx_set_options(_client_ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2);
+
+ const int security_level = 2;
+ SSLUtils::ssl_ctx_set_security_level(_client_ssl_ctx, security_level);
+
+ SSLUtils::ssl_ctx_set_verify(_client_ssl_ctx, SSL_VERIFY_PEER, NULL);
+ if (SSLUtils::ssl_ctx_load_verify_locations(_client_ssl_ctx, root_certs, NULL) != 1) {
+ if (log_is_enabled(Error, jbooster, rpc)) {
+ SSLUtils::err_print_errors_fp(stderr);
+ }
+ vm_exit_during_initialization("Failed to load root cert.");
+ }
+}
+
int ClientStream::connect_to_server() {
close_stream();
const int retries = 3;
@@ -58,10 +84,16 @@ int ClientStream::connect_to_server() {
int conn_fd;
JB_THROW(try_to_connect_once(&conn_fd, _server_address, _server_port, _timeout_ms));
assert(conn_fd >= 0 && errno == 0, "sanity");
- init_stream(conn_fd);
+
+ SSL* ssl = nullptr;
+ if (_client_ssl_ctx != nullptr) {
+ JB_THROW(try_to_ssl_connect(&ssl, conn_fd));
+ assert(ssl != nullptr && errno == 0, "sanity");
+ }
+ init_stream(conn_fd, ssl);
return 0;
} JB_TRY_BREAKABLE_END
- JB_CATCH(ECONNREFUSED, EBADF) {
+ JB_CATCH(ECONNREFUSED, EBADF, JBErr::BAD_SSL) {
last_err = JB_ERR;
} JB_CATCH_REST() {
last_err = JB_ERR;
@@ -69,7 +101,7 @@ int ClientStream::connect_to_server() {
} JB_CATCH_END;
}
- if (last_err == ECONNREFUSED || last_err == EBADF) {
+ if (last_err == ECONNREFUSED || last_err == EBADF || last_err == JBErr::BAD_SSL) {
constexpr const char* fmt = "Failed to connect to the JBooster server! Retried %d times.";
if (JBoosterCrashIfNoServer) {
fatal(fmt, retries);
@@ -119,7 +151,9 @@ int ClientStream::sync_session_meta__client(bool* has_remote_clr, bool* has_remo
RpcCompatibility comp;
uint64_t client_random_id = cdm.random_id();
JClientArguments* program_args = cdm.program_args();
- JB_RETURN(send_request(MessageType::ClientSessionMeta, &comp, &client_random_id, program_args));
+ JClientBoostLevel boost_level = cdm.boost_level();
+
+ JB_RETURN(send_request(MessageType::ClientSessionMeta, &comp, &client_random_id, program_args, &boost_level));
uint64_t server_random_id;
uint32_t session_id, program_id;
@@ -176,21 +210,21 @@ int ClientStream::connect_and_init_session(bool* use_clr, bool* use_cds, bool* u
JB_THROW(sync_session_meta__client(&has_remote_clr, &has_remote_cds, &has_remote_aot));
JB_THROW(request_cache_file(use_clr,
- cdm.is_clr_allowed(),
+ cdm.boost_level().is_clr_allowed(),
FileUtils::is_file(cdm.cache_clr_path()),
has_remote_clr,
cdm.cache_clr_path(),
MessageType::GetClassLoaderResourceCache));
JB_THROW(request_cache_file(use_cds,
- cdm.is_cds_allowed(),
+ cdm.boost_level().is_cds_allowed(),
FileUtils::is_file(cdm.cache_cds_path()),
has_remote_cds,
cdm.cache_cds_path(),
MessageType::GetAggressiveCDSCache));
JB_THROW(request_cache_file(use_aot,
- cdm.is_aot_allowed(),
+ cdm.boost_level().is_aot_allowed(),
FileUtils::is_file(cdm.cache_aot_path()),
has_remote_aot,
cdm.cache_aot_path(),
diff --git a/src/hotspot/share/jbooster/net/clientStream.hpp b/src/hotspot/share/jbooster/net/clientStream.hpp
index 1f185644f..3c4d0fc8c 100644
--- a/src/hotspot/share/jbooster/net/clientStream.hpp
+++ b/src/hotspot/share/jbooster/net/clientStream.hpp
@@ -28,6 +28,8 @@
class ClientStream: public CommunicationStream {
private:
+ static SSL_CTX* _client_ssl_ctx;
+
const char* const _server_address;
const char* const _server_port;
const uint32_t _timeout_ms;
@@ -36,6 +38,8 @@ private:
private:
static int try_to_connect_once(int* res_fd, const char* address, const char* port, uint32_t timeout_ms);
+ static int try_to_ssl_connect(SSL** res_ssl, int conn_fd);
+ static bool verify_cert(SSL* ssl);
int request_cache_file(bool* use_it,
bool allowed_to_use,
@@ -55,6 +59,8 @@ public:
ClientStream(const char* address, const char* port, uint32_t timeout_ms, Thread* thread);
~ClientStream();
+ static void client_init_ssl_ctx(const char* root_certs);
+
void set_inform_before_close(bool should) { _inform_before_close = should; }
int connect_and_init_session(bool* use_clr, bool* use_cds, bool* use_aot);
diff --git a/src/hotspot/share/jbooster/net/communicationStream.cpp b/src/hotspot/share/jbooster/net/communicationStream.cpp
index f0898170c..cdb4b8fa7 100644
--- a/src/hotspot/share/jbooster/net/communicationStream.cpp
+++ b/src/hotspot/share/jbooster/net/communicationStream.cpp
@@ -22,6 +22,7 @@
*/
#include "jbooster/net/communicationStream.inline.hpp"
+#include "jbooster/net/sslUtils.hpp"
#include "runtime/os.inline.hpp"
#ifdef ASSERT
#include "runtime/thread.inline.hpp"
@@ -54,19 +55,27 @@ void CommunicationStream::handle_net_err(int comm_size, bool is_recv) {
return;
}
+int CommunicationStream::read_from_fd_or_ssl(char* buf, size_t size) {
+ if (_ssl == nullptr) {
+ return os::recv(_conn_fd, buf, size, 0);
+ } else {
+ return SSLUtils::ssl_read(_ssl, buf, size);
+ }
+}
+
uint32_t CommunicationStream::read_once_from_stream(char* buf, uint32_t size) {
- int read_size = os::recv(_conn_fd, buf, (size_t) size, 0);
- if (read_size <= 0) {
- handle_net_err(read_size, true);
- return 0;
- }
- return (uint32_t) read_size;
+ int read_size = read_from_fd_or_ssl(buf, size);
+ if (read_size <= 0) {
+ handle_net_err(read_size, true);
+ return 0;
+ }
+ return (uint32_t) read_size;
}
uint32_t CommunicationStream::read_all_from_stream(char* buf, uint32_t size) {
uint32_t total_read_size = 0;
while (total_read_size < size) {
- int read_size = os::recv(_conn_fd, buf + total_read_size, (size_t) (size - total_read_size), 0);
+ int read_size = read_from_fd_or_ssl(buf + total_read_size, (size_t) (size - total_read_size));
if (read_size <= 0) {
handle_net_err(read_size, true);
break;
@@ -76,8 +85,16 @@ uint32_t CommunicationStream::read_all_from_stream(char* buf, uint32_t size) {
return total_read_size;
}
+int CommunicationStream::write_to_fd_or_ssl(char* buf, size_t size) {
+ if (_ssl == nullptr) {
+ return os::send(_conn_fd, buf, size, 0);
+ } else {
+ return SSLUtils::ssl_write(_ssl, buf, size);
+ }
+}
+
uint32_t CommunicationStream::write_once_to_stream(char* buf, uint32_t size) {
- int written_size = os::send(_conn_fd, buf, size, 0);
+ int written_size = write_to_fd_or_ssl(buf, size);
if (written_size <= 0) {
handle_net_err(written_size, false);
return 0;
@@ -88,7 +105,7 @@ uint32_t CommunicationStream::write_once_to_stream(char* buf, uint32_t size) {
uint32_t CommunicationStream::write_all_to_stream(char* buf, uint32_t size) {
uint32_t total_written_size = 0;
while (total_written_size < size) {
- int written_size = os::send(_conn_fd, buf + total_written_size, (size_t) (size - total_written_size), 0);
+ int written_size = write_to_fd_or_ssl(buf + total_written_size, (size_t) (size - total_written_size));
if (written_size <= 0) {
handle_net_err(written_size, false);
break;
@@ -99,6 +116,8 @@ uint32_t CommunicationStream::write_all_to_stream(char* buf, uint32_t size) {
}
void CommunicationStream::close_stream() {
+ SSLUtils::shutdown_and_free_ssl(_ssl);
+
if (_conn_fd >= 0) {
log_trace(jbooster, rpc)("Connection closed. stream_id=%u.", stream_id());
os::close(_conn_fd);
diff --git a/src/hotspot/share/jbooster/net/communicationStream.hpp b/src/hotspot/share/jbooster/net/communicationStream.hpp
index 7b2cfd9db..926221986 100644
--- a/src/hotspot/share/jbooster/net/communicationStream.hpp
+++ b/src/hotspot/share/jbooster/net/communicationStream.hpp
@@ -30,6 +30,8 @@
#include "utilities/globalDefinitions.hpp"
class Thread;
+typedef struct ssl_st SSL;
+typedef struct ssl_ctx_st SSL_CTX;
/**
* Base class of ServerStream and ClientStream.
@@ -39,6 +41,7 @@ class Thread;
class CommunicationStream: public CHeapObj<mtJBooster> {
private:
int _conn_fd; // generated by the OS
+ SSL* _ssl;
uint32_t _stream_id; // generated by the server
int _errno;
@@ -56,6 +59,8 @@ private:
int get_errno() { return _errno; }
int get_and_clear_errno() { int eno = _errno; _errno = 0; return eno; }
int return_errno_or_flag(int flag) { return get_errno() ? get_and_clear_errno() : flag; }
+ int read_from_fd_or_ssl(char* buf, size_t size);
+ int write_to_fd_or_ssl(char* buf, size_t size);
uint32_t read_once_from_stream(char* buf, uint32_t size);
uint32_t read_all_from_stream(char* buf, uint32_t size);
@@ -71,6 +76,7 @@ private:
protected:
CommunicationStream(Thread* thread):
_conn_fd(-1),
+ _ssl(nullptr),
_stream_id(0),
_errno(0),
_msg_recv(SerializationMode::DESERIALIZE, this),
@@ -80,7 +86,11 @@ protected:
virtual ~CommunicationStream() { close_stream(); }
- void init_stream(int conn_fd) { _conn_fd = conn_fd; }
+ void init_stream(int conn_fd, SSL* ssl) {
+ _conn_fd = conn_fd;
+ _ssl = ssl;
+ }
+
void close_stream();
int recv_message();
diff --git a/src/hotspot/share/jbooster/net/errorCode.hpp b/src/hotspot/share/jbooster/net/errorCode.hpp
index 8dddd31f0..625ef6951 100644
--- a/src/hotspot/share/jbooster/net/errorCode.hpp
+++ b/src/hotspot/share/jbooster/net/errorCode.hpp
@@ -29,6 +29,7 @@
#define JB_ERROR_CODES(f) \
f(CONN_CLOSED, "Connection has been closed" ) \
f(CONN_CLOSED_BY_PEER, "Connection is closed by the other end" ) \
+ f(BAD_SSL, "Unexpected SSL error during initialization" ) \
f(BAD_MSG_SIZE, "Unexpected size of the received message" ) \
f(BAD_MSG_TYPE, "Unexpected message type of the received message" ) \
f(BAD_MSG_DATA, "Unexpected payload data of the received message" ) \
diff --git a/src/hotspot/share/jbooster/net/serverListeningThread.cpp b/src/hotspot/share/jbooster/net/serverListeningThread.cpp
index 0f7b5dc8d..f01ab7bf1 100644
--- a/src/hotspot/share/jbooster/net/serverListeningThread.cpp
+++ b/src/hotspot/share/jbooster/net/serverListeningThread.cpp
@@ -26,6 +26,7 @@
#include "classfile/vmSymbols.hpp"
#include "jbooster/net/serverListeningThread.hpp"
#include "jbooster/net/serverStream.hpp"
+#include "jbooster/net/sslUtils.hpp"
#include "jbooster/server/serverDataManager.hpp"
#include "jbooster/server/serverMessageHandler.hpp"
#include "logging/log.hpp"
@@ -38,6 +39,7 @@
#include "runtime/thread.inline.hpp"
ServerListeningThread* ServerListeningThread::_singleton = nullptr;
+SSL_CTX* ServerListeningThread::_server_ssl_ctx = nullptr;
/**
* This function is called in the main thread.
@@ -45,7 +47,21 @@ ServerListeningThread* ServerListeningThread::_singleton = nullptr;
ServerListeningThread* ServerListeningThread::start_thread(const char* address,
uint16_t port,
uint32_t timeout_ms,
+ const char* ssl_key,
+ const char* ssl_cert,
TRAPS) {
+ if ((ssl_key == nullptr && ssl_cert != nullptr) || (ssl_key != nullptr && ssl_cert == nullptr)) {
+ log_error(jbooster, rpc)("You must include --ssl-cert and --ssl-key together.");
+ vm_exit(1);
+ }
+ if (ssl_key != nullptr && ssl_cert != nullptr) {
+ if (!SSLUtils::init_ssl_lib()) {
+ log_error(jbooster, rpc)("Failed to load all functions from OpenSSL Dynamic Library.");
+ vm_exit(1);
+ }
+ server_init_ssl_ctx(ssl_key, ssl_cert);
+ }
+
JavaThread* new_thread = new JavaThread(&server_listener_thread_entry);
guarantee(new_thread != nullptr && new_thread->osthread() != nullptr, "sanity");
guarantee(_singleton == nullptr, "sanity");
@@ -74,6 +90,35 @@ ServerListeningThread* ServerListeningThread::start_thread(const char* address,
return _singleton;
}
+void ServerListeningThread::server_init_ssl_ctx(const char* ssl_key, const char* ssl_cert) {
+ SSLUtils::openssl_init_ssl();
+
+ _server_ssl_ctx = SSLUtils::ssl_ctx_new(SSLUtils::sslv23_server_method());
+ if (_server_ssl_ctx == nullptr) {
+ log_error(jbooster, rpc)("Failed to create SSL context");
+ vm_exit(1);
+ }
+
+ SSLUtils::ssl_ctx_set_options(_server_ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2);
+
+ const int security_level = 2;
+ SSLUtils::ssl_ctx_set_security_level(_server_ssl_ctx, security_level);
+
+ const char* error_description = nullptr;
+ if (SSLUtils::ssl_ctx_use_certificate_file(_server_ssl_ctx, ssl_cert, SSL_FILETYPE_PEM) != 1) {
+ error_description = "Failed to add certificate file to SSL context.";
+ SSLUtils::handle_ssl_ctx_error(error_description);
+ }
+ if (SSLUtils::ssl_ctx_use_privatekey_file(_server_ssl_ctx, ssl_key, SSL_FILETYPE_PEM) != 1) {
+ error_description = "Failed to add private key file to SSL context.";
+ SSLUtils::handle_ssl_ctx_error(error_description);
+ }
+ if (SSLUtils::ssl_ctx_check_private_key(_server_ssl_ctx) != 1) {
+ error_description = "Private key doesn't match certificate.";
+ SSLUtils::handle_ssl_ctx_error(error_description);
+ }
+}
+
void ServerListeningThread::server_listener_thread_entry(JavaThread* thread, TRAPS) {
JB_TRY {
JB_THROW(_singleton->run_listener(thread));
@@ -109,7 +154,7 @@ uint32_t ServerListeningThread::new_stream_id() {
/**
* Add the new connection to the connection thread pool.
*/
-void ServerListeningThread::handle_new_connection(int conn_fd, TRAPS) {
+void ServerListeningThread::handle_new_connection(int conn_fd, SSL* ssl, TRAPS) {
ThreadInVMfromNative tiv(THREAD);
ResourceMark rm(THREAD);
HandleMark hm(THREAD);
@@ -117,12 +162,14 @@ void ServerListeningThread::handle_new_connection(int conn_fd, TRAPS) {
JavaValue result(T_BOOLEAN);
JavaCallArguments args;
args.push_int(conn_fd);
+ args.push_long((jlong)(uintptr_t) ssl);
JavaCalls::call_static(&result, ServerDataManager::get().main_klass(),
vmSymbols::receiveConnection_name(),
- vmSymbols::int_bool_signature(),
+ vmSymbols::receiveConnection_signature(),
&args, CATCH);
if (!result.get_jboolean()) {
log_warning(jbooster, rpc)("Failed to handle the new connection as the thread pool is full.");
+ SSLUtils::shutdown_and_free_ssl(ssl);
os::close(conn_fd);
}
}
@@ -133,11 +180,11 @@ void ServerListeningThread::handle_new_connection(int conn_fd, TRAPS) {
* This function is called in another java thread (not in ServerListeningThread thread).
* So do not use `this` here.
*/
-void ServerListeningThread::handle_connection(int conn_fd) {
+void ServerListeningThread::handle_connection(int conn_fd, long ssl) {
JavaThread* THREAD = JavaThread::current();
ThreadToNativeFromVM ttn(THREAD);
- ServerStream* server_stream = new ServerStream(conn_fd, THREAD);
+ ServerStream* server_stream = new ServerStream(conn_fd, (SSL*)(uintptr_t) ssl, THREAD);
ThreadServerStreamMark tssm(server_stream, true, THREAD);
server_stream->handle_meta_request(new_stream_id());
if (server_stream->is_stream_closed()) return;
diff --git a/src/hotspot/share/jbooster/net/serverListeningThread.hpp b/src/hotspot/share/jbooster/net/serverListeningThread.hpp
index 49f5efb3f..abf6e4f79 100644
--- a/src/hotspot/share/jbooster/net/serverListeningThread.hpp
+++ b/src/hotspot/share/jbooster/net/serverListeningThread.hpp
@@ -25,10 +25,15 @@
#define SHARE_JBOOSTER_NET_SERVERLISTENINGTHREAD_HPP
#include "runtime/thread.hpp"
+#include <netdb.h> // for addrinfo
+
+typedef struct ssl_st SSL;
+typedef struct ssl_ctx_st SSL_CTX;
class ServerListeningThread : public CHeapObj<mtJBooster> {
private:
static ServerListeningThread* _singleton;
+ static SSL_CTX* _server_ssl_ctx;
JavaThread* const _the_java_thread;
const char* const _address;
@@ -40,13 +45,15 @@ private:
volatile bool _exit_flag;
private:
+ static void server_init_ssl_ctx(const char* ssl_key, const char* ssl_cert);
static void server_listener_thread_entry(JavaThread* thread, TRAPS);
ServerListeningThread(JavaThread* the_java_thread, const char* address, uint16_t port, uint32_t timeout_ms);
uint32_t new_stream_id();
- void handle_new_connection(int conn_fd, TRAPS);
+ bool prepare_and_handle_new_connection(int server_fd, sockaddr_in* acc_addr, socklen_t* acc_addrlen, TRAPS);
+ void handle_new_connection(int conn_fd, SSL* ssl, TRAPS);
int run_listener(TRAPS);
@@ -54,6 +61,8 @@ public:
static ServerListeningThread* start_thread(const char* address,
uint16_t port,
uint32_t timeout_ms,
+ const char* ssl_key,
+ const char* ssl_cert,
TRAPS);
~ServerListeningThread();
@@ -61,7 +70,7 @@ public:
bool get_exit_flag() { return _exit_flag; }
void set_exit_flag() { _exit_flag = true; }
- void handle_connection(int conn_fd);
+ void handle_connection(int conn_fd, long ssl);
};
#endif // SHARE_JBOOSTER_NET_SERVERLISTENINGTHREAD_HPP
diff --git a/src/hotspot/share/jbooster/net/serverStream.cpp b/src/hotspot/share/jbooster/net/serverStream.cpp
index a3e7fa5c6..838364fca 100644
--- a/src/hotspot/share/jbooster/net/serverStream.cpp
+++ b/src/hotspot/share/jbooster/net/serverStream.cpp
@@ -30,16 +30,16 @@
#include "runtime/thread.hpp"
#include "runtime/timerTrace.hpp"
-ServerStream::ServerStream(int conn_fd):
+ServerStream::ServerStream(int conn_fd, SSL* ssl):
CommunicationStream(Thread::current_or_null()),
_session_data(nullptr) {
- init_stream(conn_fd);
+ init_stream(conn_fd, ssl);
}
-ServerStream::ServerStream(int conn_fd, Thread* thread):
+ServerStream::ServerStream(int conn_fd, SSL* ssl, Thread* thread):
CommunicationStream(thread),
_session_data(nullptr) {
- init_stream(conn_fd);
+ init_stream(conn_fd, ssl);
}
ServerStream::~ServerStream() {
@@ -52,8 +52,8 @@ uint32_t ServerStream::session_id() {
void ServerStream::set_session_data(JClientSessionData* sd) {
JClientSessionData* old_sd = _session_data;
- if (sd == old_sd) return;
- // Do not call sd->ref_cnt().inc() here as it has been inc when obtained.
+ // Do not let `sd` increase 1 here as it has been increased when obtained.
+ // But let `old_sd` decrease 1 even if `sd == old_sd` for the same reason.
if (old_sd != nullptr) {
old_sd->ref_cnt().dec_and_update_time();
}
@@ -105,7 +105,8 @@ int ServerStream::sync_session_meta__server() {
RpcCompatibility comp;
uint64_t client_random_id;
JClientArguments program_args(false); // on-stack allocation to prevent memory leakage
- JB_RETURN(parse_request(&comp, &client_random_id, &program_args));
+ JClientBoostLevel boost_level;
+ JB_RETURN(parse_request(&comp, &client_random_id, &program_args, &boost_level));
const char* unsupport_reason = nullptr;
if (!program_args.check_compatibility_with_server(&unsupport_reason)) {
@@ -115,7 +116,7 @@ int ServerStream::sync_session_meta__server() {
JB_RETURN(JBErr::ABORT_CUR_PHRASE);
}
- JClientSessionData* sd = sdm.create_session(client_random_id, &program_args, Thread::current());
+ JClientSessionData* sd = sdm.create_session(client_random_id, &program_args, boost_level, Thread::current());
JClientProgramData* pd = sd->program_data();
set_session_data(sd);
@@ -123,8 +124,8 @@ int ServerStream::sync_session_meta__server() {
uint32_t session_id = sd->session_id();
uint32_t program_id = pd->program_id();
bool has_remote_clr = pd->clr_cache_state().is_cached();
- bool has_remote_cds = pd->cds_cache_state().is_cached();
- bool has_remote_aot = pd->aot_cache_state().is_cached();
+ bool has_remote_cds = boost_level.is_cds_agg_enabled() ? pd->agg_cds_cache_state().is_cached() : pd->dy_cds_cache_state().is_cached();
+ bool has_remote_aot = boost_level.is_aot_pgo_enabled() ? pd->aot_pgo_cache_state().is_cached() : pd->aot_static_cache_state().is_cached();
JB_RETURN(send_response(stream_id_addr(), &server_random_id, &session_id, &program_id,
&has_remote_clr, &has_remote_cds, &has_remote_aot));
log_info(jbooster, rpc)("New client: session_id=%u, program_id=%u, "
@@ -138,10 +139,10 @@ int ServerStream::sync_session_meta__server() {
BOOL_TO_STR(has_remote_aot),
stream_id());
- return handle_sync_requests(pd);
+ return handle_sync_requests(pd, boost_level.is_cds_agg_enabled(), boost_level.is_aot_pgo_enabled());
}
-int ServerStream::handle_sync_requests(JClientProgramData* pd) {
+int ServerStream::handle_sync_requests(JClientProgramData* pd, bool enable_cds_agg, bool enable_aot_pgo) {
bool not_end = true;
do {
MessageType type;
@@ -155,13 +156,15 @@ int ServerStream::handle_sync_requests(JClientProgramData* pd) {
}
case MessageType::GetAggressiveCDSCache: {
TraceTime tt("Send cds", TRACETIME_LOG(Info, jbooster));
- FileWrapper file(pd->cds_cache_state().file_path(), SerializationMode::SERIALIZE);
+ const char* cds_file_path = enable_cds_agg ? pd->agg_cds_cache_state().file_path() : pd->dy_cds_cache_state().file_path();
+ FileWrapper file(cds_file_path, SerializationMode::SERIALIZE);
JB_RETURN(file.send_file(this));
break;
}
case MessageType::GetLazyAOTCache: {
TraceTime tt("Send aot", TRACETIME_LOG(Info, jbooster));
- FileWrapper file(pd->aot_cache_state().file_path(), SerializationMode::SERIALIZE);
+ const char* aot_file_path = enable_aot_pgo ? pd->aot_pgo_cache_state().file_path() : pd->aot_static_cache_state().file_path();
+ FileWrapper file(aot_file_path, SerializationMode::SERIALIZE);
JB_RETURN(file.send_file(this));
break;
}
diff --git a/src/hotspot/share/jbooster/net/serverStream.hpp b/src/hotspot/share/jbooster/net/serverStream.hpp
index 56d05dabb..7239813cd 100644
--- a/src/hotspot/share/jbooster/net/serverStream.hpp
+++ b/src/hotspot/share/jbooster/net/serverStream.hpp
@@ -40,11 +40,11 @@ private:
int sync_stream_meta__server();
int resync_session_and_stream_meta__server();
- int handle_sync_requests(JClientProgramData* pd);
+ int handle_sync_requests(JClientProgramData* pd, bool enable_cds_agg, bool enable_aot_pgo);
public:
- ServerStream(int conn_fd);
- ServerStream(int conn_fd, Thread* thread);
+ ServerStream(int conn_fd, SSL* ssl);
+ ServerStream(int conn_fd, SSL* ssl, Thread* thread);
~ServerStream();
void handle_meta_request(uint32_t stream_id);
diff --git a/src/hotspot/share/jbooster/net/sslUtils.cpp b/src/hotspot/share/jbooster/net/sslUtils.cpp
new file mode 100644
index 000000000..96a159871
--- /dev/null
+++ b/src/hotspot/share/jbooster/net/sslUtils.cpp
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2020, 2024, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "logging/log.hpp"
+#include "jbooster/net/sslUtils.hpp"
+#include "runtime/java.hpp"
+#include <dlfcn.h>
+#include <string.h>
+
+void* SSLUtils::_lib_handle = nullptr;
+enum SSLUtils::SSLVersion SSLUtils::_version = V0;
+const char* SSLUtils::OPENSSL_VERSION_1_0 = "OpenSSL 1.0.";
+const char* SSLUtils::OPENSSL_VERSION_1_1 = "OpenSSL 1.1.";
+const char* SSLUtils::OPENSSL_VERSION_3_X = "OpenSSL 3.";
+
+SSLUtils::openssl_version_func_t SSLUtils::_openssl_version = nullptr;
+SSLUtils::openssl_init_ssl_func_t SSLUtils::_openssl_init_ssl = nullptr;
+SSLUtils::ssl_ctx_new_func_t SSLUtils::_ssl_ctx_new = nullptr;
+SSLUtils::sslv23_client_method_func_t SSLUtils::_sslv23_client_method = nullptr;
+SSLUtils::sslv23_server_method_func_t SSLUtils::_sslv23_server_method = nullptr;
+SSLUtils::ssl_ctx_ctrl_func_t SSLUtils::_ssl_ctx_ctrl = nullptr;
+SSLUtils::ssl_ctx_set_options_func_t SSLUtils::_ssl_ctx_set_options = nullptr;
+SSLUtils::ssl_ctx_set_cipher_list_func_t SSLUtils::_ssl_ctx_set_cipher_list = nullptr;
+SSLUtils::ssl_ctx_set_ciphersuites_func_t SSLUtils::_ssl_ctx_set_ciphersuites = nullptr;
+SSLUtils::ssl_ctx_set_verify_func_t SSLUtils::_ssl_ctx_set_verify = nullptr;
+SSLUtils::ssl_ctx_load_verify_locations_func_t SSLUtils::_ssl_ctx_load_verify_locations = nullptr;
+SSLUtils::ssl_ctx_use_certificate_file_func_t SSLUtils::_ssl_ctx_use_certificate_file = nullptr;
+SSLUtils::ssl_ctx_use_privatekey_file_func_t SSLUtils::_ssl_ctx_use_privatekey_file = nullptr;
+SSLUtils::ssl_ctx_check_private_key_func_t SSLUtils::_ssl_ctx_check_private_key = nullptr;
+SSLUtils::ssl_ctx_set_security_level_func_t SSLUtils::_ssl_ctx_set_security_level = nullptr;
+SSLUtils::ssl_new_func_t SSLUtils::_ssl_new = nullptr;
+SSLUtils::ssl_set_fd_func_t SSLUtils::_ssl_set_fd = nullptr;
+SSLUtils::ssl_get_error_func_t SSLUtils::_ssl_get_error = nullptr;
+SSLUtils::ssl_accept_func_t SSLUtils::_ssl_accept = nullptr;
+SSLUtils::ssl_connect_func_t SSLUtils::_ssl_connect = nullptr;
+SSLUtils::ssl_read_func_t SSLUtils::_ssl_read = nullptr;
+SSLUtils::ssl_write_func_t SSLUtils::_ssl_write = nullptr;
+SSLUtils::ssl_shutdown_func_t SSLUtils::_ssl_shutdown = nullptr;
+SSLUtils::ssl_free_func_t SSLUtils::_ssl_free = nullptr;
+SSLUtils::ssl_ctx_free_func_t SSLUtils::_ssl_ctx_free = nullptr;
+SSLUtils::ssl_get_peer_certificate_func_t SSLUtils::_ssl_get_peer_certificate = nullptr;
+SSLUtils::ssl_get_verify_result_func_t SSLUtils::_ssl_get_verify_result = nullptr;
+SSLUtils::err_peak_error_func_t SSLUtils::_err_peak_error = nullptr;
+SSLUtils::err_error_string_n_func_t SSLUtils::_err_error_string_n = nullptr;
+SSLUtils::err_get_error_func_t SSLUtils::_err_get_error = nullptr;
+SSLUtils::err_print_errors_fp_func_t SSLUtils::_err_print_errors_fp = nullptr;
+
+static void* open_ssl_lib() {
+ const char* const lib_names[] = {
+ "libssl.so.3",
+ "libssl.so.1.1",
+ "libssl.so.1.0.0",
+ "libssl.so.10",
+ "libssl.so"
+ };
+ const int lib_names_len = sizeof(lib_names) / sizeof(lib_names[0]);
+
+ void* res = nullptr;
+ for (int i = 0; i < lib_names_len; ++i) {
+ res = ::dlopen(lib_names[i], RTLD_NOW);
+ if (res != nullptr) {
+ break;
+ }
+ }
+ return res;
+}
+
+void SSLUtils::find_ssl_version() {
+ const char* openssl_version_res = nullptr;
+ _openssl_version = (openssl_version_func_t)::dlsym(_lib_handle, "OpenSSL_version");
+ if (_openssl_version) {
+ openssl_version_res = openssl_version();
+ if (0 == strncmp(openssl_version_res, OPENSSL_VERSION_1_1, strlen(OPENSSL_VERSION_1_1))) {
+ _version = V1_1;
+ } else if (0 == strncmp(openssl_version_res, OPENSSL_VERSION_3_X, strlen(OPENSSL_VERSION_3_X))) {
+ _version = V3;
+ }
+ } else {
+ _openssl_version = (openssl_version_func_t) ::dlsym(_lib_handle, "SSLeay_version");
+ if (_openssl_version) {
+ openssl_version_res = openssl_version();
+ if (0 == strncmp(openssl_version_res, OPENSSL_VERSION_1_0, strlen(OPENSSL_VERSION_1_0))) {
+ _version = V1_0;
+ }
+ }
+ }
+}
+
+void SSLUtils::find_address_in_dynamic_lib() {
+ if (_version == V3) {
+ _ssl_get_peer_certificate = (ssl_get_peer_certificate_func_t) ::dlsym(_lib_handle, "SSL_get1_peer_certificate");
+ } else {
+ _ssl_get_peer_certificate = (ssl_get_peer_certificate_func_t) ::dlsym(_lib_handle, "SSL_get_peer_certificate");
+ }
+
+ _openssl_init_ssl = (openssl_init_ssl_func_t) ::dlsym(_lib_handle, "OPENSSL_init_ssl");
+ _sslv23_client_method = (sslv23_client_method_func_t) ::dlsym(_lib_handle, "TLS_client_method");
+ _sslv23_server_method = (sslv23_server_method_func_t) ::dlsym(_lib_handle, "TLS_server_method");
+ _ssl_ctx_new = (ssl_ctx_new_func_t) ::dlsym(_lib_handle, "SSL_CTX_new");
+ _ssl_ctx_ctrl = (ssl_ctx_ctrl_func_t) ::dlsym(_lib_handle, "SSL_CTX_ctrl");
+ _ssl_ctx_set_options = (ssl_ctx_set_options_func_t) ::dlsym(_lib_handle, "SSL_CTX_set_options");
+ _ssl_ctx_set_cipher_list = (ssl_ctx_set_cipher_list_func_t) ::dlsym(_lib_handle, "SSL_CTX_set_cipher_list");
+ _ssl_ctx_set_ciphersuites = (ssl_ctx_set_ciphersuites_func_t) ::dlsym(_lib_handle, "SSL_CTX_set_ciphersuites");
+ _ssl_ctx_set_verify = (ssl_ctx_set_verify_func_t) ::dlsym(_lib_handle, "SSL_CTX_set_verify");
+ _ssl_ctx_load_verify_locations = (ssl_ctx_load_verify_locations_func_t) ::dlsym(_lib_handle, "SSL_CTX_load_verify_locations");
+ _ssl_ctx_use_certificate_file = (ssl_ctx_use_certificate_file_func_t) ::dlsym(_lib_handle, "SSL_CTX_use_certificate_file");
+ _ssl_ctx_use_privatekey_file = (ssl_ctx_use_privatekey_file_func_t) ::dlsym(_lib_handle, "SSL_CTX_use_PrivateKey_file");
+ _ssl_ctx_check_private_key = (ssl_ctx_check_private_key_func_t) ::dlsym(_lib_handle, "SSL_CTX_check_private_key");
+ _ssl_ctx_set_security_level = (ssl_ctx_set_security_level_func_t) ::dlsym(_lib_handle, "SSL_CTX_set_security_level");
+ _ssl_new = (ssl_new_func_t) ::dlsym(_lib_handle, "SSL_new");
+ _ssl_set_fd = (ssl_set_fd_func_t) ::dlsym(_lib_handle, "SSL_set_fd");
+ _ssl_get_error = (ssl_get_error_func_t) ::dlsym(_lib_handle, "SSL_get_error");
+ _ssl_accept = (ssl_accept_func_t) ::dlsym(_lib_handle, "SSL_accept");
+ _ssl_connect = (ssl_connect_func_t) ::dlsym(_lib_handle, "SSL_connect");
+ _ssl_read = (ssl_read_func_t) ::dlsym(_lib_handle, "SSL_read");
+ _ssl_write = (ssl_write_func_t) ::dlsym(_lib_handle, "SSL_write");
+ _ssl_shutdown = (ssl_shutdown_func_t) ::dlsym(_lib_handle, "SSL_shutdown");
+ _ssl_free = (ssl_free_func_t) ::dlsym(_lib_handle, "SSL_free");
+ _ssl_ctx_free = (ssl_ctx_free_func_t) ::dlsym(_lib_handle, "SSL_CTX_free");
+ _ssl_get_verify_result = (ssl_get_verify_result_func_t) ::dlsym(_lib_handle, "SSL_get_verify_result");
+ _err_peak_error = (err_peak_error_func_t) ::dlsym(_lib_handle, "ERR_peek_error");
+ _err_error_string_n = (err_error_string_n_func_t) ::dlsym(_lib_handle, "ERR_error_string_n");
+ _err_get_error = (err_get_error_func_t) ::dlsym(_lib_handle, "ERR_get_error");
+ _err_print_errors_fp = (err_print_errors_fp_func_t) ::dlsym(_lib_handle, "ERR_print_errors_fp");
+}
+
+bool SSLUtils::check_if_find_all_functions() {
+ if (
+ (_openssl_version == nullptr) ||
+ (_openssl_init_ssl == nullptr) ||
+ (_ssl_ctx_new == nullptr) ||
+ (_sslv23_client_method == nullptr) ||
+ (_sslv23_server_method == nullptr) ||
+ (_ssl_ctx_ctrl == nullptr) ||
+ (_ssl_ctx_set_options == nullptr) ||
+ (_ssl_ctx_set_cipher_list == nullptr) ||
+ (_ssl_ctx_set_ciphersuites == nullptr) ||
+ (_ssl_ctx_set_verify == nullptr) ||
+ (_ssl_ctx_load_verify_locations == nullptr) ||
+ (_ssl_ctx_use_certificate_file == nullptr) ||
+ (_ssl_ctx_use_privatekey_file == nullptr) ||
+ (_ssl_ctx_check_private_key == nullptr) ||
+ (_ssl_ctx_set_security_level == nullptr) ||
+ (_ssl_new == nullptr) ||
+ (_ssl_set_fd == nullptr) ||
+ (_ssl_get_error == nullptr) ||
+ (_ssl_accept == nullptr) ||
+ (_ssl_connect == nullptr) ||
+ (_ssl_read == nullptr) ||
+ (_ssl_write == nullptr) ||
+ (_ssl_shutdown == nullptr) ||
+ (_ssl_free == nullptr) ||
+ (_ssl_ctx_free == nullptr) ||
+ (_ssl_get_peer_certificate == nullptr) ||
+ (_ssl_get_verify_result == nullptr) ||
+ (_err_peak_error == nullptr) ||
+ (_err_error_string_n == nullptr) ||
+ (_err_get_error == nullptr) ||
+ (_err_print_errors_fp == nullptr)
+ ) { return false; }
+ return true;
+}
+
+bool SSLUtils::init_ssl_lib() {
+ _lib_handle = open_ssl_lib();
+ if (_lib_handle == nullptr) {
+ return false;
+ }
+
+ find_ssl_version();
+ if (_version == V0) {
+ return false;
+ } else if (_version == V1_0) {
+ log_error(jbooster, rpc)("JBooster only supports OpenSSL 1.1.0+.");
+ return false;
+ }
+
+ find_address_in_dynamic_lib();
+ return check_if_find_all_functions();
+}
+
+void SSLUtils::shutdown_and_free_ssl(SSL*& ssl) {
+ if (ssl != nullptr) {
+ SSLUtils::ssl_shutdown(ssl);
+ SSLUtils::ssl_free(ssl);
+ ssl = nullptr;
+ }
+}
+
+void SSLUtils::handle_ssl_ctx_error(const char* error_description) {
+ log_error(jbooster, rpc)("%s", error_description);
+ if (log_is_enabled(Error, jbooster, rpc)) {
+ SSLUtils::err_print_errors_fp(stderr);
+ }
+ vm_exit(1);
+}
+
+void SSLUtils::handle_ssl_error(SSL* ssl, int ret, const char* error_description) {
+ const char* errno_copy = strerror(errno);
+ int error = SSLUtils::ssl_get_error(ssl, ret);
+ unsigned long earliest_error = SSLUtils::err_peak_error();
+
+ char error_string[256] = {0};
+ SSLUtils::err_error_string_n(earliest_error, error_string, sizeof(error_string));
+
+ log_error(jbooster, rpc)("%s! Error Code: %d, Earliest Error: %lu, Error String: %s, Errno: %s",
+ error_description, error, earliest_error, error_string, errno_copy);
+ if (log_is_enabled(Error, jbooster, rpc)) {
+ SSLUtils::err_print_errors_fp(stderr);
+ }
+}
\ No newline at end of file
diff --git a/src/hotspot/share/jbooster/net/sslUtils.hpp b/src/hotspot/share/jbooster/net/sslUtils.hpp
new file mode 100644
index 000000000..0b8253b40
--- /dev/null
+++ b/src/hotspot/share/jbooster/net/sslUtils.hpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2020, 2024, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_JBOOSTER_UTILITIES_SSLUtils_HPP
+#define SHARE_JBOOSTER_UTILITIES_SSLUtils_HPP
+
+#include "memory/allocation.hpp"
+#include <openssl/ssl.h>
+
+class SSLUtils : AllStatic {
+ typedef const char* (*openssl_version_func_t)(int num);
+ typedef int (*openssl_init_ssl_func_t)(uint64_t opts, const void* settings);
+ typedef SSL_CTX* (*ssl_ctx_new_func_t)(const SSL_METHOD* meth);
+ typedef SSL_METHOD* (*sslv23_client_method_func_t)(void);
+ typedef SSL_METHOD* (*sslv23_server_method_func_t)(void);
+ typedef long (*ssl_ctx_ctrl_func_t)(SSL_CTX* ctx, int cmd, long larg, void* parg);
+ typedef uint64_t (*ssl_ctx_set_options_func_t)(SSL_CTX* ctx, uint64_t options);
+ typedef int (*ssl_ctx_set_cipher_list_func_t)(SSL_CTX* ctx, const char* str);
+ typedef int (*ssl_ctx_set_ciphersuites_func_t)(SSL_CTX* ctx, const char* str);
+ typedef void (*ssl_ctx_set_verify_func_t)(SSL_CTX* ctx, int mode, SSL_verify_cb callback);
+ typedef int (*ssl_ctx_load_verify_locations_func_t)(SSL_CTX* ctx, const char* CAfile, const char* CApath);
+ typedef int (*ssl_ctx_use_certificate_file_func_t)(SSL_CTX* ctx, const char* file, int type);
+ typedef int (*ssl_ctx_use_privatekey_file_func_t)(SSL_CTX* ctx, const char* file, int type);
+ typedef int (*ssl_ctx_check_private_key_func_t)(const SSL_CTX* ctx);
+ typedef void (*ssl_ctx_set_security_level_func_t)(SSL_CTX *ctx, int level);
+ typedef SSL* (*ssl_new_func_t)(SSL_CTX* ctx);
+ typedef int (*ssl_set_fd_func_t)(SSL* s, int fd);
+ typedef int (*ssl_get_error_func_t)(const SSL* s, int ret_code);
+ typedef int (*ssl_accept_func_t)(const SSL* ssl);
+ typedef int (*ssl_connect_func_t)(const SSL* ssl);
+ typedef int (*ssl_read_func_t)(SSL* ssl, void* buf, int num);
+ typedef int (*ssl_write_func_t)(SSL* ssl, const void* buf, int num);
+ typedef int (*ssl_shutdown_func_t)(SSL* ssl);
+ typedef void (*ssl_free_func_t)(SSL* ssl);
+ typedef void (*ssl_ctx_free_func_t)(SSL_CTX* ctx);
+ typedef X509* (*ssl_get_peer_certificate_func_t)(const SSL* ssl);
+ typedef long (*ssl_get_verify_result_func_t)(const SSL* ssl);
+ typedef unsigned long (*err_peak_error_func_t)(void);
+ typedef void (*err_error_string_n_func_t)(unsigned long e, char *buf, size_t len);
+ typedef unsigned long (*err_get_error_func_t)(void);
+ typedef void (*err_print_errors_fp_func_t)(FILE *fp);
+
+ static enum SSLVersion {
+ V0, V1_0, V1_1, V3
+ } _version;
+
+ static void* _lib_handle;
+ static const char* OPENSSL_VERSION_1_0;
+ static const char* OPENSSL_VERSION_1_1;
+ static const char* OPENSSL_VERSION_3_X;
+
+ static openssl_version_func_t _openssl_version;
+ static openssl_init_ssl_func_t _openssl_init_ssl;
+ static ssl_ctx_new_func_t _ssl_ctx_new;
+ static sslv23_client_method_func_t _sslv23_client_method;
+ static sslv23_server_method_func_t _sslv23_server_method;
+ static ssl_ctx_ctrl_func_t _ssl_ctx_ctrl;
+ static ssl_ctx_set_options_func_t _ssl_ctx_set_options;
+ static ssl_ctx_set_cipher_list_func_t _ssl_ctx_set_cipher_list;
+ static ssl_ctx_set_ciphersuites_func_t _ssl_ctx_set_ciphersuites;
+ static ssl_ctx_set_verify_func_t _ssl_ctx_set_verify;
+ static ssl_ctx_load_verify_locations_func_t _ssl_ctx_load_verify_locations;
+ static ssl_ctx_use_certificate_file_func_t _ssl_ctx_use_certificate_file;
+ static ssl_ctx_use_privatekey_file_func_t _ssl_ctx_use_privatekey_file;
+ static ssl_ctx_check_private_key_func_t _ssl_ctx_check_private_key;
+ static ssl_ctx_set_security_level_func_t _ssl_ctx_set_security_level;
+ static ssl_new_func_t _ssl_new;
+ static ssl_set_fd_func_t _ssl_set_fd;
+ static ssl_get_error_func_t _ssl_get_error;
+ static ssl_accept_func_t _ssl_accept;
+ static ssl_connect_func_t _ssl_connect;
+ static ssl_read_func_t _ssl_read;
+ static ssl_write_func_t _ssl_write;
+ static ssl_shutdown_func_t _ssl_shutdown;
+ static ssl_free_func_t _ssl_free;
+ static ssl_ctx_free_func_t _ssl_ctx_free;
+ static ssl_get_peer_certificate_func_t _ssl_get_peer_certificate;
+ static ssl_get_verify_result_func_t _ssl_get_verify_result;
+ static err_peak_error_func_t _err_peak_error;
+ static err_error_string_n_func_t _err_error_string_n;
+ static err_get_error_func_t _err_get_error;
+ static err_print_errors_fp_func_t _err_print_errors_fp;
+
+public:
+ static bool init_ssl_lib();
+ static void find_ssl_version();
+ static void find_address_in_dynamic_lib();
+ static bool check_if_find_all_functions();
+
+ static const char* openssl_version() { return (*_openssl_version)(0); }
+
+ static int openssl_init_ssl() { return (*_openssl_init_ssl)(0, NULL); }
+ static SSL_CTX* ssl_ctx_new(const SSL_METHOD* meth) { return (*_ssl_ctx_new)(meth); }
+ static SSL_METHOD* sslv23_client_method() { return (*_sslv23_client_method)(); }
+ static SSL_METHOD* sslv23_server_method() { return (*_sslv23_server_method)(); }
+ static long ssl_ctx_ctrl(SSL_CTX* ctx, int cmd, long larg, void* parg) { return (*_ssl_ctx_ctrl)(ctx, cmd, larg, parg); }
+ static uint64_t ssl_ctx_set_options(SSL_CTX* ctx, uint64_t options) { return (*_ssl_ctx_set_options)(ctx, options); };
+ static int ssl_ctx_set_cipher_list(SSL_CTX* ctx, const char* str) { return (*_ssl_ctx_set_cipher_list)(ctx, str); };
+ static int ssl_ctx_set_ciphersuites(SSL_CTX* ctx, const char* str) { return (*_ssl_ctx_set_ciphersuites)(ctx, str); };
+ static void ssl_ctx_set_verify(SSL_CTX* ctx, int mode, SSL_verify_cb callback) { return (*_ssl_ctx_set_verify)(ctx, mode, callback); }
+ static int ssl_ctx_load_verify_locations(SSL_CTX* ctx, const char* CAfile, const char* CApath) { return (*_ssl_ctx_load_verify_locations)(ctx, CAfile, CApath); }
+ static int ssl_ctx_use_certificate_file(SSL_CTX* ctx, const char* file, int type) { return (*_ssl_ctx_use_certificate_file)(ctx, file, type); }
+ static int ssl_ctx_use_privatekey_file(SSL_CTX* ctx, const char* file, int type) { return (*_ssl_ctx_use_privatekey_file)(ctx, file, type); }
+ static void ssl_ctx_set_security_level(SSL_CTX *ctx, int level) { return (*_ssl_ctx_set_security_level)(ctx, level); }
+ static int ssl_ctx_check_private_key(const SSL_CTX* ctx) { return (*_ssl_ctx_check_private_key)(ctx); }
+ static SSL* ssl_new(SSL_CTX* ctx) { return (*_ssl_new)(ctx); }
+ static int ssl_set_fd(SSL* s, int fd) { return (*_ssl_set_fd)(s, fd); }
+ static int ssl_get_error(const SSL* s, int ret_code) { return (*_ssl_get_error)(s, ret_code); }
+ static int ssl_accept(const SSL* ssl) { return (*_ssl_accept)(ssl); }
+ static int ssl_connect(const SSL* ssl) { return (*_ssl_connect)(ssl); }
+ static int ssl_read(SSL* ssl, void* buf, int num) { return (*_ssl_read)(ssl, buf, num); }
+ static int ssl_write(SSL* ssl, const void* buf, int num) { return (*_ssl_write)(ssl, buf, num); }
+ static int ssl_shutdown(SSL* ssl) { return (*_ssl_shutdown)(ssl); }
+ static void ssl_free(SSL* ssl) { return (*_ssl_free)(ssl); }
+ static void ssl_ctx_free(SSL_CTX* ctx) { return (*_ssl_ctx_free)(ctx); }
+ static X509* ssl_get_peer_certificate(const SSL* ssl) { return (*_ssl_get_peer_certificate)(ssl); }
+ static long ssl_get_verify_result(const SSL* ssl) { return (*_ssl_get_verify_result)(ssl); }
+ static unsigned long err_peak_error() { return (*_err_peak_error)(); }
+ static void err_error_string_n(unsigned long e, char *buf, size_t len) { return (*_err_error_string_n)(e, buf, len); }
+ static unsigned long err_get_error() { return (*_err_get_error)(); }
+ static void err_print_errors_fp(FILE *fp) { return (*_err_print_errors_fp)(fp); };
+
+ static void shutdown_and_free_ssl(SSL*& ssl);
+ static void handle_ssl_ctx_error(const char* error_description);
+ static void handle_ssl_error(SSL* ssl, int ret, const char* error_description);
+};
+
+#endif // SHARE_JBOOSTER_UTILITIES_SSLUtils_HPP
diff --git a/src/hotspot/share/jbooster/server/serverDataManager.cpp b/src/hotspot/share/jbooster/server/serverDataManager.cpp
index 8753102a4..b2f36c4e5 100644
--- a/src/hotspot/share/jbooster/server/serverDataManager.cpp
+++ b/src/hotspot/share/jbooster/server/serverDataManager.cpp
@@ -170,15 +170,13 @@ jlong RefCntWithTime::no_ref_time(jlong current_time) const {
// -------------------------------- JClientCacheState ---------------------------------
-JClientCacheState::JClientCacheState(): _is_allowed(false),
- _state(NOT_GENERATED),
+JClientCacheState::JClientCacheState(): _state(NOT_GENERATED),
_file_path(nullptr),
_file_timestamp(0) {
// The real assignment is in JClientProgramData::JClientProgramData().
}
-void JClientCacheState::init(bool allow, const char* file_path) {
- _is_allowed = allow;
+void JClientCacheState::init(const char* file_path) {
_file_path = file_path;
bool file_exists = FileUtils::is_file(file_path);
_state = file_exists ? GENERATED : NOT_GENERATED;
@@ -259,6 +257,11 @@ bool JClientCacheState::is_cached() {
return false;
}
+const char* JClientCacheState::cache_state_str() {
+ return is_cached() ? "generated" : (is_being_generated() ? "generating" : "none");
+}
+
+
void JClientCacheState::remove_file() {
if (is_cached()) {
remove_file_and_set_not_generated_sync();
@@ -277,18 +280,16 @@ JClientProgramData::JClientProgramData(uint32_t program_id, JClientArguments* pr
_program_args->program_entry(),
_program_args->is_jar(),
_program_args->hash());
- bool allow_clr = _program_args->jbooster_allow_clr();
- bool allow_cds = _program_args->jbooster_allow_cds();
- bool allow_aot = _program_args->jbooster_allow_aot();
- bool allow_pgo = _program_args->jbooster_allow_pgo();
const char* clr_path = JBoosterManager::calc_cache_path(sd, _program_str_id, "clr.log");
- const char* cds_path = JBoosterManager::calc_cache_path(sd, _program_str_id, "cds.jsa");
- const char* aot_path_suffix = allow_pgo ? "aot-pgo.so" : "aot.so";
- const char* aot_path = JBoosterManager::calc_cache_path(sd, _program_str_id, aot_path_suffix);
- clr_cache_state().init(allow_clr, clr_path);
- cds_cache_state().init(allow_cds, cds_path);
- aot_cache_state().init(allow_aot, aot_path);
- _using_pgo = allow_pgo;
+ const char* dy_cds_path = JBoosterManager::calc_cache_path(sd, _program_str_id, "cds-dy.jsa");
+ const char* agg_cds_path = JBoosterManager::calc_cache_path(sd, _program_str_id, "cds-agg.jsa");
+ const char* aot_static_path = JBoosterManager::calc_cache_path(sd, _program_str_id, "aot-static.so");
+ const char* aot_pgo_path = JBoosterManager::calc_cache_path(sd, _program_str_id, "aot-pgo.so");
+ clr_cache_state().init(clr_path);
+ dy_cds_cache_state().init(dy_cds_path);
+ agg_cds_cache_state().init(agg_cds_path);
+ aot_static_cache_state().init(aot_static_path);
+ aot_pgo_cache_state().init(aot_pgo_path);
}
JClientProgramData::~JClientProgramData() {
@@ -357,10 +358,12 @@ public:
JClientSessionData::JClientSessionData(uint32_t session_id,
uint64_t client_random_id,
- JClientProgramData* program_data):
+ JClientProgramData* program_data,
+ JClientBoostLevel boost_level):
_session_id(session_id),
_random_id(client_random_id),
_program_data(program_data),
+ _boost_level(boost_level),
_cl_s2c(),
_cl_c2s(),
_k_c2s(),
@@ -540,7 +543,7 @@ void ServerDataManager::init_cache_path(const char* optional_cache_path) {
FileUtils::mkdirs(JBoosterCachePath);
}
-void ServerDataManager::init_phase3(int server_port, int connection_timeout, int cleanup_timeout, const char* cache_path, TRAPS) {
+void ServerDataManager::init_phase3(int server_port, int connection_timeout, int cleanup_timeout, const char* cache_path, const char* ssl_key, const char* ssl_cert, TRAPS) {
JBoosterManager::server_only();
init_cache_path(cache_path);
@@ -548,7 +551,7 @@ void ServerDataManager::init_phase3(int server_port, int connection_timeout, int
ServerControlThread::set_unused_shared_data_cleanup_timeout(cleanup_timeout);
_singleton->_control_thread = ServerControlThread::start_thread(CHECK);
- _singleton->_listening_thread = ServerListeningThread::start_thread(JBoosterAddress, (uint16_t) server_port, connection_timeout, CHECK);
+ _singleton->_listening_thread = ServerListeningThread::start_thread(JBoosterAddress, (uint16_t) server_port, connection_timeout, ssl_key, ssl_cert, CHECK);
}
/**
@@ -610,10 +613,11 @@ JClientSessionData* ServerDataManager::get_session(uint32_t session_id, Thread*
*/
JClientSessionData* ServerDataManager::create_session(uint64_t client_random_id,
JClientArguments* program_args,
+ JClientBoostLevel boost_level,
Thread* thread) {
uint32_t session_id = Atomic::add(&_next_session_allocation_id, 1u);
JClientProgramData* pd = get_or_create_program(program_args, thread);
- JClientSessionData* sd = new JClientSessionData(session_id, client_random_id, pd);
+ JClientSessionData* sd = new JClientSessionData(session_id, client_random_id, pd, boost_level);
JClientSessionData** res = _sessions.put_if_absent(session_id, sd, thread);
guarantee(res != nullptr && *res == sd, "sanity");
diff --git a/src/hotspot/share/jbooster/server/serverDataManager.hpp b/src/hotspot/share/jbooster/server/serverDataManager.hpp
index 9181acd10..2cb7d2de0 100644
--- a/src/hotspot/share/jbooster/server/serverDataManager.hpp
+++ b/src/hotspot/share/jbooster/server/serverDataManager.hpp
@@ -133,7 +133,6 @@ class JClientCacheState final: public StackObj {
static const int BEING_GENERATED = 1;
static const int GENERATED = 2;
- bool _is_allowed;
volatile int _state;
const char* _file_path;
uint64_t _file_timestamp;
@@ -149,9 +148,7 @@ public:
JClientCacheState();
~JClientCacheState();
- void init(bool allow, const char* file_path);
-
- bool is_allowed() { return _is_allowed; }
+ void init(const char* file_path);
// <cache_dir>/server/cache-<parogram_str_id>-<cache-name>
const char* file_path() { return _file_path; }
@@ -167,6 +164,7 @@ public:
// Unlike the APIs above, the APIs above only change the atomic variables,
// while the following APIs checks whether the cache file exists.
bool is_cached();
+ const char* cache_state_str();
void remove_file();
};
@@ -188,10 +186,10 @@ private:
RefCntWithTime _ref_cnt;
JClientCacheState _clr_cache_state;
- JClientCacheState _cds_cache_state;
- JClientCacheState _aot_cache_state;
-
- bool _using_pgo; // use pgo if or not, as boost level 4
+ JClientCacheState _dy_cds_cache_state;
+ JClientCacheState _agg_cds_cache_state;
+ JClientCacheState _aot_static_cache_state;
+ JClientCacheState _aot_pgo_cache_state;
NONCOPYABLE(JClientProgramData);
@@ -211,9 +209,10 @@ public:
RefCntWithTime& ref_cnt() { return _ref_cnt; }
JClientCacheState& clr_cache_state() { return _clr_cache_state; }
- JClientCacheState& cds_cache_state() { return _cds_cache_state; }
- JClientCacheState& aot_cache_state() { return _aot_cache_state; }
- bool using_pgo() { return _using_pgo; }
+ JClientCacheState& dy_cds_cache_state() { return _dy_cds_cache_state; }
+ JClientCacheState& agg_cds_cache_state() { return _agg_cds_cache_state; }
+ JClientCacheState& aot_static_cache_state() { return _aot_static_cache_state; }
+ JClientCacheState& aot_pgo_cache_state() { return _aot_pgo_cache_state; }
};
/**
@@ -248,6 +247,8 @@ private:
JClientProgramData* const _program_data;
+ JClientBoostLevel _boost_level;
+
// server-side CLD pointer -> client-side CLD pointer
AddressMap _cl_s2c;
// client-side CLD pointer -> server-side CLD pointer
@@ -269,7 +270,7 @@ private:
static bool remove_address(AddressMap& table, address key, Thread* thread);
public:
- JClientSessionData(uint32_t session_id, uint64_t client_random_id, JClientProgramData* program_data);
+ JClientSessionData(uint32_t session_id, uint64_t client_random_id, JClientProgramData* program_data, JClientBoostLevel boost_level);
~JClientSessionData();
uint32_t session_id() const { return _session_id; }
@@ -278,6 +279,8 @@ public:
JClientProgramData* program_data() const { return _program_data; }
+ const JClientBoostLevel& boost_level() const { return _boost_level; }
+
address client_cld_address(ClassLoaderData* server_data, Thread* thread);
ClassLoaderData* server_cld_address(address client_data, Thread* thread);
ClassLoaderData* add_class_loader_if_absent(address client_cld_addr,
@@ -399,7 +402,7 @@ public:
static jint init_phase1();
static void init_phase2(TRAPS) { /* do nothing */ }
- static void init_phase3(int server_port, int connection_timeout, int cleanup_timeout, const char* cache_path, TRAPS);
+ static void init_phase3(int server_port, int connection_timeout, int cleanup_timeout, const char* cache_path, const char* ssl_key, const char* ssl_cert, TRAPS);
// $HOME/.jbooster/server
const char* cache_dir_path() { return _cache_dir_path; }
@@ -416,6 +419,7 @@ public:
JClientSessionData* get_session(uint32_t session_id, Thread* thread);
JClientSessionData* create_session(uint64_t client_random_id,
JClientArguments* program_args,
+ JClientBoostLevel boost_level,
Thread* thread);
bool try_remove_session(uint32_t session_id, Thread* thread);
diff --git a/src/hotspot/share/jbooster/server/serverDataManagerLog.cpp b/src/hotspot/share/jbooster/server/serverDataManagerLog.cpp
index 47e9c6b01..c0a7b8647 100644
--- a/src/hotspot/share/jbooster/server/serverDataManagerLog.cpp
+++ b/src/hotspot/share/jbooster/server/serverDataManagerLog.cpp
@@ -93,19 +93,20 @@ public:
bool operator () (ServerDataManager::JClientProgramDataMap::KVNode* kv_node) {
JClientProgramData* pd = kv_node->value();
JClientCacheState& clr = pd->clr_cache_state();
- JClientCacheState& cds = pd->cds_cache_state();
- JClientCacheState& aot = pd->aot_cache_state();
- const char* clr_stat = (clr.is_cached() ? "generated" : (clr.is_being_generated() ? "generating" : "none"));
- const char* cds_stat = (cds.is_cached() ? "generated" : (cds.is_being_generated() ? "generating" : "none"));
- const char* aot_stat = (aot.is_cached() ? "generated" : (aot.is_being_generated() ? "generating" : "none"));
+ JClientCacheState& agg_cds = pd->agg_cds_cache_state();
+ JClientCacheState& dy_cds = pd->dy_cds_cache_state();
+ JClientCacheState& aot_static = pd->aot_static_cache_state();
+ JClientCacheState& aot_pgo = pd->aot_pgo_cache_state();
OUT_1("-");
OUT_2("program_id: %u", pd->program_id());
OUT_2("program_name: %s", pd->program_args()->program_name());
OUT_2("program_hash: %x", pd->program_args()->hash());
OUT_2("ref_cnt: %d", pd->ref_cnt().get());
- OUT_2("clr_cache: %s", clr_stat);
- OUT_2("cds_cache: %s", cds_stat);
- OUT_2("aot_cache: %s", aot_stat);
+ OUT_2("clr_cache: %s", clr.cache_state_str());
+ OUT_2("dy_cds_cache: %s", dy_cds.cache_state_str());
+ OUT_2("agg_cds_cache: %s", agg_cds.cache_state_str());
+ OUT_2("aot_static_cache: %s", aot_static.cache_state_str());
+ OUT_2("aot_pgo_cache: %s", aot_pgo.cache_state_str());
OUT_2("class_loader_size: " SIZE_FORMAT, pd->class_loaders()->size());
if (pd->class_loaders()->size() > 0) {
OUT_2("class_loaders:");
diff --git a/src/hotspot/share/jbooster/server/serverMessageHandler.cpp b/src/hotspot/share/jbooster/server/serverMessageHandler.cpp
index 962e93cc7..49c25efb1 100644
--- a/src/hotspot/share/jbooster/server/serverMessageHandler.cpp
+++ b/src/hotspot/share/jbooster/server/serverMessageHandler.cpp
@@ -275,7 +275,7 @@ int ServerMessageHandler::request_methods_not_compile(GrowableArray<Method*>* me
}
int ServerMessageHandler::request_client_cache(MessageType msg_type, JClientCacheState& cache) {
- if (cache.is_allowed() && !cache.is_cached() && cache.set_being_generated()) {
+ if (!cache.is_cached() && cache.set_being_generated()) {
JB_TRY {
JB_THROW(ss().send_request(msg_type));
FileWrapper file(cache.file_path(), SerializationMode::DESERIALIZE);
@@ -294,10 +294,14 @@ int ServerMessageHandler::request_client_cache(MessageType msg_type, JClientCach
int ServerMessageHandler::handle_cache_file_sync_task(TRAPS) {
DebugUtils::assert_thread_nonjava_or_in_native();
- JClientProgramData* pd = ss().session_data()->program_data();
+ JClientSessionData* sd = ss().session_data();
+ JClientProgramData* pd = sd->program_data();
+ bool enabling_cds_agg = sd->boost_level().is_cds_agg_enabled();
JB_RETURN(request_client_cache(MessageType::CacheClassLoaderResource, pd->clr_cache_state()));
- JB_RETURN(request_client_cache(MessageType::CacheAggressiveCDS, pd->cds_cache_state()));
+
+ JClientCacheState& cds_cache_state = enabling_cds_agg ? pd->agg_cds_cache_state() : pd->dy_cds_cache_state();
+ JB_RETURN(request_client_cache(MessageType::CacheAggressiveCDS, cds_cache_state));
JB_RETURN(ss().send_request(MessageType::EndOfCurrentPhase));
return 0;
@@ -306,8 +310,10 @@ int ServerMessageHandler::handle_cache_file_sync_task(TRAPS) {
int ServerMessageHandler::handle_lazy_aot_compilation_task(TRAPS) {
DebugUtils::assert_thread_in_native();
- JClientProgramData* pd = ss().session_data()->program_data();
- JClientCacheState& aot_cache_state = pd->aot_cache_state();
+ JClientSessionData* sd = ss().session_data();
+ JClientProgramData* pd = sd->program_data();
+ bool enabling_aot_pgo = sd->boost_level().is_aot_pgo_enabled();
+ JClientCacheState& aot_cache_state = enabling_aot_pgo ? pd->aot_pgo_cache_state() : pd->aot_static_cache_state();
ResourceMark rm(THREAD);
GrowableArray<InstanceKlass*> klasses_to_compile;
GrowableArray<Method*> methods_to_compile;
@@ -321,7 +327,7 @@ int ServerMessageHandler::handle_lazy_aot_compilation_task(TRAPS) {
JB_THROW(request_missing_class_loaders(THREAD));
JB_THROW(request_missing_klasses(THREAD));
JB_THROW(request_methods_to_compile(&klasses_to_compile, &methods_to_compile, THREAD));
- if (pd->using_pgo()) {
+ if (enabling_aot_pgo) {
JB_THROW(request_methods_not_compile(&methods_not_compile, THREAD));
JB_THROW(request_method_data(THREAD));
}
@@ -338,7 +344,7 @@ int ServerMessageHandler::handle_lazy_aot_compilation_task(TRAPS) {
JB_RETURN(try_to_compile_lazy_aot(&klasses_to_compile,
&methods_to_compile,
&methods_not_compile,
- pd->using_pgo(),
+ enabling_aot_pgo,
THREAD));
} else { // not compile in current thread
if (aot_cache_state.is_being_generated()) {
@@ -358,10 +364,10 @@ int ServerMessageHandler::handle_lazy_aot_compilation_task(TRAPS) {
int ServerMessageHandler::try_to_compile_lazy_aot(GrowableArray<InstanceKlass*>* klasses_to_compile,
GrowableArray<Method*>* methods_to_compile,
GrowableArray<Method*>* methods_not_compile,
- bool use_pgo,
+ bool enabling_aot_pgo,
TRAPS) {
JClientProgramData* pd = ss().session_data()->program_data();
- JClientCacheState& aot_cache_state = pd->aot_cache_state();
+ JClientCacheState& aot_cache_state = enabling_aot_pgo ? pd->aot_pgo_cache_state() : pd->aot_static_cache_state();
if (klasses_to_compile->is_empty()) {
// the expected path without plugin
aot_cache_state.set_not_generated();
@@ -376,17 +382,17 @@ int ServerMessageHandler::try_to_compile_lazy_aot(GrowableArray<InstanceKlass*>*
ThreadInVMfromNative tiv(THREAD);
if (methods_to_compile->is_empty()) {
- successful = LazyAOT::compile_classes_by_graal(session_id, file_path, klasses_to_compile, use_pgo, THREAD);
+ successful = LazyAOT::compile_classes_by_graal(session_id, file_path, klasses_to_compile, enabling_aot_pgo, THREAD);
} else {
successful = LazyAOT::compile_methods_by_graal(session_id, file_path, klasses_to_compile,
- methods_to_compile, methods_not_compile, use_pgo, THREAD);
+ methods_to_compile, methods_not_compile, enabling_aot_pgo, THREAD);
}
if (successful) {
guarantee(!HAS_PENDING_EXCEPTION, "sanity");
chmod(file_path, S_IREAD);
aot_cache_state.set_generated();
- log_info(jbooster, compilation)("Successfully comiled %d classes. session_id=%u.",
+ log_info(jbooster, compilation)("Successfully compiled %d classes. session_id=%u.",
klasses_to_compile->length(),
ss().session_id());
} else if (HAS_PENDING_EXCEPTION) {
diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp
index c9d3768cd..b5a3bf95d 100644
--- a/src/hotspot/share/prims/jvm.cpp
+++ b/src/hotspot/share/prims/jvm.cpp
@@ -3860,20 +3860,28 @@ JVM_END
// JBooster ////////////////////////////////////////////////////////////////////////
-JVM_ENTRY(void, JVM_JBoosterInitVM(JNIEnv *env, jint server_port, jint connection_timeout, jint cleanup_timeout, jstring cache_path))
+JVM_ENTRY(void, JVM_JBoosterInitVM(JNIEnv *env, jint server_port, jint connection_timeout, jint cleanup_timeout, jstring cache_path, jstring ssl_key, jstring ssl_cert))
#if INCLUDE_JBOOSTER
ResourceMark rm(THREAD);
const char* cache_path_c = NULL;
if (cache_path != NULL) {
cache_path_c = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(cache_path));
}
- ServerDataManager::init_phase3(server_port, connection_timeout, cleanup_timeout, cache_path_c, THREAD);
+ const char* ssl_key_c = NULL;
+ if (ssl_key != NULL) {
+ ssl_key_c = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(ssl_key));
+ }
+ const char* ssl_cert_c = NULL;
+ if (ssl_cert != NULL) {
+ ssl_cert_c = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(ssl_cert));
+ }
+ ServerDataManager::init_phase3(server_port, connection_timeout, cleanup_timeout, cache_path_c, ssl_key_c, ssl_cert_c, THREAD);
#endif // INCLUDE_JBOOSTER
JVM_END
-JVM_ENTRY(void, JVM_JBoosterHandleConnection(JNIEnv *env, jint connection_fd))
+JVM_ENTRY(void, JVM_JBoosterHandleConnection(JNIEnv *env, jint connection_fd, jlong connection_ssl))
#if INCLUDE_JBOOSTER
- ServerDataManager::get().listening_thread()->handle_connection(connection_fd);
+ ServerDataManager::get().listening_thread()->handle_connection(connection_fd, connection_ssl);
#endif // INCLUDE_JBOOSTER
JVM_END
diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp
index 43da20b3f..a77f30b8c 100644
--- a/src/hotspot/share/runtime/java.cpp
+++ b/src/hotspot/share/runtime/java.cpp
@@ -526,7 +526,7 @@ void before_exit(JavaThread* thread, bool halt) {
os::terminate_signal_thread();
#if INCLUDE_CDS
- if (DynamicDumpSharedSpaces JBOOSTER_ONLY(&& !(UseJBooster && ClientDataManager::get().is_cds_allowed()))) {
+ if (DynamicDumpSharedSpaces JBOOSTER_ONLY(&& !(UseJBooster && ClientDataManager::get().boost_level().is_cds_allowed()))) {
ExceptionMark em(thread);
DynamicArchive::dump();
if (thread->has_pending_exception()) {
diff --git a/src/jdk.jbooster/share/classes/jdk/jbooster/JBooster.java b/src/jdk.jbooster/share/classes/jdk/jbooster/JBooster.java
index 642fbafa6..db5d916ac 100644
--- a/src/jdk.jbooster/share/classes/jdk/jbooster/JBooster.java
+++ b/src/jdk.jbooster/share/classes/jdk/jbooster/JBooster.java
@@ -99,7 +99,8 @@ public final class JBooster {
connectionPool = new ConnectionPool();
Main.initForJBooster();
initInVM(options.getServerPort(), options.getConnectionTimeout(),
- options.getCleanupTimeout(), options.getCachePath());
+ options.getCleanupTimeout(), options.getCachePath(),
+ options.getSSLKey(), options.getSSLCert());
}
private static void loop() {
@@ -167,8 +168,8 @@ public final class JBooster {
/**
* This method is invoked only in C++.
*/
- private static boolean receiveConnection(int connectionFd) {
- return connectionPool.execute(() -> handleConnection(connectionFd));
+ private static boolean receiveConnection(int connectionFd, long connectionSSL) {
+ return connectionPool.execute(() -> handleConnection(connectionFd, connectionSSL));
}
/**
@@ -198,9 +199,9 @@ public final class JBooster {
return false;
}
- private static native void initInVM(int serverPort, int connectionTimeout, int cleanupTimeout, String cachePath);
+ private static native void initInVM(int serverPort, int connectionTimeout, int cleanupTimeout, String cachePath, String sslKey, String sslCert);
- private static native void handleConnection(int connectionFd);
+ private static native void handleConnection(int connectionFd, long connectionSSL);
static native void printStoredClientData(boolean printAll);
diff --git a/src/jdk.jbooster/share/classes/jdk/jbooster/Options.java b/src/jdk.jbooster/share/classes/jdk/jbooster/Options.java
index 869e5ca97..f81d69287 100644
--- a/src/jdk.jbooster/share/classes/jdk/jbooster/Options.java
+++ b/src/jdk.jbooster/share/classes/jdk/jbooster/Options.java
@@ -93,6 +93,18 @@ public final class Options {
protected void process(Options options, String arg) {
options.interactive = false;
}
+ }, new Option(of("--ssl-key"), "file-path",
+ "The file path to save server SSL key.") {
+ @Override
+ protected void process(Options options, String arg) {
+ options.sslKey = arg;
+ }
+ }, new Option(of("--ssl-cert"), "file-path",
+ "The file path to save server SSL certificate.") {
+ @Override
+ protected void process(Options options, String arg) {
+ options.sslCert = arg;
+ }
}};
private int serverPort = UNSET_PORT;
@@ -100,6 +112,8 @@ public final class Options {
private int cleanupTimeout = CLEANUP_TIMEOUT;
private String cachePath = null; // set on C++ side
private boolean interactive = true;
+ private String sslKey = null;
+ private String sslCert = null;
public int getServerPort() {
return serverPort;
@@ -121,6 +135,14 @@ public final class Options {
return interactive;
}
+ public String getSSLKey() {
+ return sslKey;
+ }
+
+ public String getSSLCert() {
+ return sslCert;
+ }
+
/**
* Parse the args of main().
*
diff --git a/src/jdk.jbooster/share/native/libjbooster/JBooster.c b/src/jdk.jbooster/share/native/libjbooster/JBooster.c
index 0c25710ae..1c489b57b 100644
--- a/src/jdk.jbooster/share/native/libjbooster/JBooster.c
+++ b/src/jdk.jbooster/share/native/libjbooster/JBooster.c
@@ -27,15 +27,15 @@
#include "jdk_jbooster_JBooster.h"
JNIEXPORT void JNICALL
-Java_jdk_jbooster_JBooster_initInVM(JNIEnv * env, jclass unused, jint server_port, jint connection_timeout, jint cleanup_timeout, jstring cache_path)
+Java_jdk_jbooster_JBooster_initInVM(JNIEnv * env, jclass unused, jint server_port, jint connection_timeout, jint cleanup_timeout, jstring cache_path, jstring ssl_key, jstring ssl_cert)
{
- JVM_JBoosterInitVM(env, server_port, connection_timeout, cleanup_timeout, cache_path);
+ JVM_JBoosterInitVM(env, server_port, connection_timeout, cleanup_timeout, cache_path, ssl_key, ssl_cert);
}
JNIEXPORT void JNICALL
-Java_jdk_jbooster_JBooster_handleConnection(JNIEnv * env, jclass unused, jint connection_fd)
+Java_jdk_jbooster_JBooster_handleConnection(JNIEnv * env, jclass unused, jint connection_fd, jlong connection_ssl)
{
- JVM_JBoosterHandleConnection(env, connection_fd);
+ JVM_JBoosterHandleConnection(env, connection_fd, connection_ssl);
}
JNIEXPORT void JNICALL
diff --git a/test/jdk/tools/jbooster/JBoosterCmdTest.java b/test/jdk/tools/jbooster/JBoosterCmdTest.java
index 98439e699..4a2c0801a 100644
--- a/test/jdk/tools/jbooster/JBoosterCmdTest.java
+++ b/test/jdk/tools/jbooster/JBoosterCmdTest.java
@@ -35,7 +35,7 @@ import static jdk.test.lib.Asserts.*;
* /test/lib
* @modules jdk.jbooster
* @build SimpleClient
- * @run main/othervm/timeout=300 JBoosterCmdTest
+ * @run main/othervm/timeout=5000 JBoosterCmdTest
*/
public class JBoosterCmdTest extends JBoosterTestBase {
diff --git a/test/jdk/tools/jbooster/JBoosterNetTest.java b/test/jdk/tools/jbooster/JBoosterNetTest.java
index a71368127..0df0e265f 100644
--- a/test/jdk/tools/jbooster/JBoosterNetTest.java
+++ b/test/jdk/tools/jbooster/JBoosterNetTest.java
@@ -36,7 +36,7 @@ import static jdk.test.lib.Asserts.*;
* /test/lib
* @modules jdk.jbooster
* @build SimpleClient
- * @run main/othervm/timeout=300 JBoosterNetTest
+ * @run main/othervm/timeout=5000 JBoosterNetTest
*/
public class JBoosterNetTest extends JBoosterTestBase {
diff --git a/test/jdk/tools/jbooster/JBoosterSSLTest.java b/test/jdk/tools/jbooster/JBoosterSSLTest.java
new file mode 100644
index 000000000..192acc6dd
--- /dev/null
+++ b/test/jdk/tools/jbooster/JBoosterSSLTest.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2020, 2024, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ import java.io.File;
+ import java.util.List;
+ import java.util.ArrayList;
+ import java.util.concurrent.TimeUnit;
+ import java.util.regex.Pattern;
+
+import static jdk.test.lib.Asserts.*;
+
+/*
+* jbooster testing.
+* @test
+* @summary Test jbooster server
+* @library ../lib
+* /test/lib
+* @modules jdk.jbooster
+* @build SimpleClient
+* @run main/othervm/timeout=5000 JBoosterSSLTest
+*/
+public class JBoosterSSLTest extends JBoosterTestBase {
+ private static void testSSLCorrectArgs(TestContext ctx) throws Exception {
+ ArrayList<String> serverArgs = new ArrayList<>(SERVER_STANDARD_ARGS);
+
+ final String sep = File.separator;
+ String testSrc = System.getProperty("test.src", "") + sep;
+
+ serverArgs.add(serverArgs.size() - 1, String.format("--ssl-cert=%sserver-cert.pem", testSrc));
+ serverArgs.add(serverArgs.size() - 1, String.format("--ssl-key=%sserver-key.pem", testSrc));
+ Process server = jbooster(ctx, List.of(), serverArgs);
+ server.waitFor(WAIT_START_TIME, TimeUnit.SECONDS);
+
+ ArrayList<String> clientArgs = new ArrayList<>(CLIENT_STANDARD_ARGS);
+ clientArgs.add(4, String.format("-XX:JBoosterServerSSLRootCerts=%sserver-cert.pem", testSrc));
+ Process client = java(ctx, clientArgs);
+ client.waitFor(WAIT_EXIT_TIME, TimeUnit.SECONDS);
+
+ assertEquals(client.exitValue(), 0, "good");
+ exitNormallyByCommandQ(server);
+ }
+
+ private static void testSSLNoArgs(TestContext ctx) throws Exception {
+ ArrayList<String> serverArgs = new ArrayList<>(SERVER_STANDARD_ARGS);
+ Process server = jbooster(ctx, List.of(), SERVER_STANDARD_ARGS);
+ server.waitFor(WAIT_START_TIME, TimeUnit.SECONDS);
+
+ ArrayList<String> clientArgs = new ArrayList<>(CLIENT_STANDARD_ARGS);
+ Process client = java(ctx, CLIENT_STANDARD_ARGS);
+ client.waitFor(WAIT_EXIT_TIME, TimeUnit.SECONDS);
+
+ assertEquals(client.exitValue(), 0, "good");
+ exitNormallyByCommandQ(server);
+ }
+
+ private static void testSSLDifferentCert(TestContext ctx) throws Exception {
+ ArrayList<String> serverArgs = new ArrayList<>(SERVER_STANDARD_ARGS);
+
+ final String sep = File.separator;
+ String testSrc = System.getProperty("test.src", "") + sep;
+
+ serverArgs.add(serverArgs.size() - 1, String.format("--ssl-cert=%sserver-cert.pem", testSrc));
+ serverArgs.add(serverArgs.size() - 1, String.format("--ssl-key=%sserver-key.pem", testSrc));
+ Process server = jbooster(ctx, List.of(), serverArgs);
+ server.waitFor(WAIT_START_TIME, TimeUnit.SECONDS);
+
+ ArrayList<String> clientArgs = new ArrayList<>(CLIENT_STANDARD_ARGS);
+ clientArgs.add(4, String.format("-XX:JBoosterServerSSLRootCerts=%sunrelated-cert.pem", testSrc));
+ Process client = java(ctx, clientArgs);
+ client.waitFor(WAIT_EXIT_TIME, TimeUnit.SECONDS);
+
+ assertNotEquals(client.exitValue(), 0, "Both certs must be the same.");
+ exitNormallyByCommandQ(server);
+ }
+
+ private static void testSSLClientNoArg(TestContext ctx) throws Exception {
+ ArrayList<String> serverArgs = new ArrayList<>(SERVER_STANDARD_ARGS);
+
+ final String sep = File.separator;
+ String testSrc = System.getProperty("test.src", "") + sep;
+
+ serverArgs.add(serverArgs.size() - 1, String.format("--ssl-cert=%sserver-cert.pem", testSrc));
+ serverArgs.add(serverArgs.size() - 1, String.format("--ssl-key=%sserver-key.pem", testSrc));
+ Process server = jbooster(ctx, List.of(), serverArgs);
+ server.waitFor(WAIT_START_TIME, TimeUnit.SECONDS);
+
+ Process client = java(ctx, CLIENT_STANDARD_ARGS);
+ client.waitFor(WAIT_EXIT_TIME, TimeUnit.SECONDS);
+
+ assertNotEquals(client.exitValue(), 0, "Client choose not to use SSL.");
+ exitNormallyByCommandQ(server);
+ }
+
+ private static void testSSLServerNoArg(TestContext ctx) throws Exception {
+ Process server = jbooster(ctx, List.of(), SERVER_STANDARD_ARGS);
+
+ final String sep = File.separator;
+ String testSrc = System.getProperty("test.src", "") + sep;
+
+ server.waitFor(WAIT_START_TIME, TimeUnit.SECONDS);
+
+ ArrayList<String> clientArgs = new ArrayList<>(CLIENT_STANDARD_ARGS);
+ clientArgs.add(4, String.format("-XX:JBoosterServerSSLRootCerts=%sserver-cert.pem", testSrc));
+ Process client = java(ctx, clientArgs);
+ client.waitFor(WAIT_EXIT_TIME, TimeUnit.SECONDS);
+
+ assertNotEquals(client.exitValue(), 0, "Server choose not to use SSL.");
+ exitNormallyByCommandQ(server);
+ }
+
+ private static void testSSLServerOneArg(TestContext ctx) throws Exception {
+ ArrayList<String> serverArgs1 = new ArrayList<>(SERVER_STANDARD_ARGS);
+
+ final String sep = File.separator;
+ String testSrc = System.getProperty("test.src", "") + sep;
+
+ serverArgs1.add(serverArgs1.size() - 1, String.format("--ssl-cert=%sserver-cert.pem", testSrc));
+ Process server1 = jbooster(ctx, List.of(), serverArgs1);
+ server1.waitFor(WAIT_START_TIME, TimeUnit.SECONDS);
+ assertEquals(server1.exitValue(), 1, "Missing Arg --ssl-key.");
+
+ ArrayList<String> serverArgs2 = new ArrayList<>(SERVER_STANDARD_ARGS);
+ serverArgs2.add(serverArgs2.size() - 1, String.format("--ssl-key=%sserver-key.pem", testSrc));
+ Process server2 = jbooster(ctx, List.of(), serverArgs2);
+ server2.waitFor(WAIT_START_TIME, TimeUnit.SECONDS);
+ assertEquals(server2.exitValue(), 1, "Missing Arg --ssl-cert.");
+ }
+
+ public static void main(String[] args) throws Exception {
+ testCases(JBoosterSSLTest.class);
+ }
+}
\ No newline at end of file
diff --git a/test/jdk/tools/jbooster/JBoosterSharedCacheTest.java b/test/jdk/tools/jbooster/JBoosterSharedCacheTest.java
new file mode 100644
index 000000000..bab3e2fa8
--- /dev/null
+++ b/test/jdk/tools/jbooster/JBoosterSharedCacheTest.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2020, 2024, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ import java.io.File;
+ import java.util.List;
+ import java.util.ArrayList;
+ import java.util.concurrent.TimeUnit;
+ import java.util.regex.Pattern;
+
+ import static jdk.test.lib.Asserts.*;
+
+ /*
+ * jbooster testing.
+ * @test
+ * @summary Test jbooster server
+ * @library ../lib
+ * /test/lib
+ * @modules jdk.jbooster
+ * @build SimpleClient
+ * @run main/othervm/timeout=5000 JBoosterSharedCacheTest
+ */
+ public class JBoosterSharedCacheTest extends JBoosterTestBase {
+
+ public static boolean checkFileNumAndCacheType(String cacheType, int num) throws Exception {
+ File dir = new File(SERVER_CACHE_PATH);
+ File[] fileList = dir.listFiles();
+ if (fileList.length != num) {
+ return false;
+ }
+
+ if (fileList != null){
+ for (File subFile : fileList) {
+ if (subFile.isFile() && subFile.getName().endsWith(cacheType)){
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public static boolean checkCacheFilesSameProgram() throws Exception {
+ File dir = new File(SERVER_CACHE_PATH);
+ File[] fileList = dir.listFiles();
+ String hash = null;
+ for (File subFile : fileList) {
+ String file_hash = subFile.getName().split("-")[2];
+ if (hash == null) {
+ hash = file_hash;
+ } else {
+ if (!hash.equals(file_hash)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private static void testCacheAtLevel1(TestContext ctx) throws Exception {
+ Process server = jbooster(ctx, List.of("-Xlog:jbooster*=trace"), SERVER_STANDARD_ARGS);
+ server.waitFor(WAIT_START_TIME, TimeUnit.SECONDS);
+
+ ArrayList<String> clientArgs = new ArrayList<>(CLIENT_STANDARD_ARGS_WITHOUT_LEVEL);
+ clientArgs.add(4, "-XX:BoostStopAtLevel=1");
+ Process p = java(ctx, clientArgs);
+ p.waitFor(WAIT_EXIT_TIME, TimeUnit.SECONDS);
+
+ assertEquals(checkFileNumAndCacheType("clr.log", 1), true, "clr not generated.");
+ exitNormallyByCommandQ(server);
+ }
+
+ private static void testCacheAtLevel2(TestContext ctx) throws Exception {
+ Process server = jbooster(ctx, List.of("-Xlog:jbooster*=trace"), SERVER_STANDARD_ARGS);
+ server.waitFor(WAIT_START_TIME, TimeUnit.SECONDS);
+
+ ArrayList<String> clientArgs = new ArrayList<>(CLIENT_STANDARD_ARGS_WITHOUT_LEVEL);
+ clientArgs.add(4, "-XX:BoostStopAtLevel=2");
+ Process p = java(ctx, clientArgs);
+ p.waitFor(WAIT_EXIT_TIME, TimeUnit.SECONDS);
+
+ assertEquals(checkFileNumAndCacheType("cds-agg.jsa", 2), true, "cds-agg not generated.");
+ exitNormallyByCommandQ(server);
+ }
+
+ private static void testCacheAtLevel3(TestContext ctx) throws Exception {
+ Process server = jbooster(ctx, List.of("-Xlog:jbooster*=trace"), SERVER_STANDARD_ARGS);
+ server.waitFor(WAIT_START_TIME, TimeUnit.SECONDS);
+
+ ArrayList<String> clientArgs = new ArrayList<>(CLIENT_STANDARD_ARGS_WITHOUT_LEVEL);
+ clientArgs.add(4, "-XX:BoostStopAtLevel=3");
+ Process p = java(ctx, clientArgs);
+ p.waitFor(WAIT_EXIT_TIME, TimeUnit.SECONDS);
+
+ Thread.currentThread().sleep(5000);
+ assertEquals(checkFileNumAndCacheType("aot-static.so", 3), true, "aot-static not generated.");
+ exitNormallyByCommandQ(server);
+ }
+
+ private static void testCacheAtLevel4(TestContext ctx) throws Exception {
+ Process server = jbooster(ctx, List.of("-Xlog:jbooster*=trace"), SERVER_STANDARD_ARGS);
+ server.waitFor(WAIT_START_TIME, TimeUnit.SECONDS);
+
+ ArrayList<String> clientArgs = new ArrayList<>(CLIENT_STANDARD_ARGS_WITHOUT_LEVEL);
+ clientArgs.add(4, "-XX:BoostStopAtLevel=4");
+ Process p = java(ctx, clientArgs);
+ p.waitFor(WAIT_EXIT_TIME, TimeUnit.SECONDS);
+
+ Thread.currentThread().sleep(5000);
+ assertEquals(checkFileNumAndCacheType("aot-pgo.so", 4), true, "aot-pgo not generated.");
+ exitNormallyByCommandQ(server);
+ }
+
+ private static void testCacheWithDyCDS(TestContext ctx) throws Exception {
+ Process server = jbooster(ctx, List.of("-Xlog:jbooster*=trace"), SERVER_STANDARD_ARGS);
+ server.waitFor(WAIT_START_TIME, TimeUnit.SECONDS);
+
+ ArrayList<String> clientArgs = new ArrayList<>(CLIENT_STANDARD_ARGS_WITHOUT_LEVEL);
+ clientArgs.add(4, "-XX:BoostStopAtLevel=4");
+ clientArgs.add(5, "-XX:-UseAggressiveCDS");
+ Process p = java(ctx, clientArgs);
+ p.waitFor(WAIT_EXIT_TIME, TimeUnit.SECONDS);
+
+ assertEquals(checkFileNumAndCacheType("cds-dy.jsa", 5), true, "cds-dy not generated.");
+ assertEquals(checkCacheFilesSameProgram(), true, "hash not same.");
+ exitNormallyByCommandQ(server);
+ }
+
+ public static void main(String[] args) throws Exception {
+ testCases(JBoosterSharedCacheTest.class);
+ }
+ }
diff --git a/test/jdk/tools/jbooster/JBoosterTestBase.java b/test/jdk/tools/jbooster/JBoosterTestBase.java
index 8f925d7f3..08792a77b 100644
--- a/test/jdk/tools/jbooster/JBoosterTestBase.java
+++ b/test/jdk/tools/jbooster/JBoosterTestBase.java
@@ -67,6 +67,9 @@ public class JBoosterTestBase {
"SimpleClient"
);
+ public static final List<String> CLIENT_STANDARD_ARGS_WITHOUT_LEVEL = CLIENT_STANDARD_ARGS.stream()
+ .filter(s -> !"-XX:BoostStopAtLevel=4".equals(s)).toList();
+
public static final List<String> CLIENT_OFFLINE_ARGS = List.of(
"-XX:+UnlockExperimentalVMOptions",
"-XX:+UseJBooster",
@@ -84,7 +87,7 @@ public class JBoosterTestBase {
public static Process jbooster(TestContext ctx, List<String> vmArgs, List<String> jboosterArgs) throws Exception {
JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jbooster");
- launcher.addVMArgs(Utils.getTestJavaOpts());
+ // launcher.addVMArgs(Utils.getTestJavaOpts());
if (vmArgs != null) {
for (String vmArg : vmArgs) {
launcher.addVMArg(vmArg);
@@ -151,6 +154,7 @@ public class JBoosterTestBase {
} finally {
for (Process p : ctx.getProcesses()) {
if (p.isAlive()) {
+ p.waitFor(WAIT_SHORT_TIME, TimeUnit.SECONDS);
p.destroyForcibly();
}
}
diff --git a/test/jdk/tools/jbooster/server-cert.pem b/test/jdk/tools/jbooster/server-cert.pem
new file mode 100644
index 000000000..923cf333a
--- /dev/null
+++ b/test/jdk/tools/jbooster/server-cert.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDjTCCAnWgAwIBAgIUUo4hM/1j2s4ZT0VPHU/1rOzu5DIwDQYJKoZIhvcNAQEL
+BQAwVjELMAkGA1UEBhMCY24xETAPBgNVBAgMCHNoYW5naGFpMREwDwYDVQQHDAhz
+aGFuZ2hhaTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMB4XDTI0
+MDYyNjEwMDcxNVoXDTI1MDYyNjEwMDcxNVowVjELMAkGA1UEBhMCY24xETAPBgNV
+BAgMCHNoYW5naGFpMREwDwYDVQQHDAhzaGFuZ2hhaTEhMB8GA1UECgwYSW50ZXJu
+ZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAoZ3+SQavSX6hZXLJtDlXe1TrNROWxySmnL3FBuEEH7SlwOoVxRW1P+ZivPp4
+vjnWDXaafb5yVc0w7A+6Clt/OFrgvhw92quxHnGGvy3IxNMdgL2lNZ6gjeUXs2IA
+59FdboSgDbJvJAcemq7v2UhbAAmq47+pQ+ZtVnF2LCN424PObGlnxJDDVb+vWTF9
+DlUvvkv3XW8anP5iPnZ0Ou91Lu4WTSvD2TZCDUVWrP52jj9H08WlTA8SUOxluixu
+f4SJ0WO767VABBkYAZ+/4fERZL4PSf6l1XLjJBFEb0rn1dECEe559OHPHjBZly0i
+t39Fc8kCfTxKVjdpBwhC98gCyQIDAQABo1MwUTAdBgNVHQ4EFgQU4fQgXJlXPnbA
+TlDDncohnRoP7mMwHwYDVR0jBBgwFoAU4fQgXJlXPnbATlDDncohnRoP7mMwDwYD
+VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEALbIy4RBXvkej98ZoxshC
+VbrVQdjTY9DkZIOIOHn2jwwyiezSI+Aff+mg0XgWEB+pC7i1CnqOk0EW2pUsTmvd
+fY2fUCrGr7mH58mq5ADwOURByPtpstFtjWNcUuiqoKGwP+hP64mf+gY8r7Gc9k9V
+zCS0e1r4i87kW2pvqdY9aJ5xNOb6PfWc31c5f8306MfnFiy/U5m2lGCs0KVkwjtm
+3Xm5hI3OYYdZ5c4mHGtVmFnzLz+moxywWu6vXYTcuDe6v2JRJ2ZB6znwNOWO56RR
+WhEssi4Szig1206d5idUgAB8OwttUtEMtT+labAvUKeeI0eiYlpsgyMbrW0VE4qQ
+bg==
+-----END CERTIFICATE-----
diff --git a/test/jdk/tools/jbooster/server-key.pem b/test/jdk/tools/jbooster/server-key.pem
new file mode 100644
index 000000000..77bf13bb3
--- /dev/null
+++ b/test/jdk/tools/jbooster/server-key.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAoZ3+SQavSX6hZXLJtDlXe1TrNROWxySmnL3FBuEEH7SlwOoV
+xRW1P+ZivPp4vjnWDXaafb5yVc0w7A+6Clt/OFrgvhw92quxHnGGvy3IxNMdgL2l
+NZ6gjeUXs2IA59FdboSgDbJvJAcemq7v2UhbAAmq47+pQ+ZtVnF2LCN424PObGln
+xJDDVb+vWTF9DlUvvkv3XW8anP5iPnZ0Ou91Lu4WTSvD2TZCDUVWrP52jj9H08Wl
+TA8SUOxluixuf4SJ0WO767VABBkYAZ+/4fERZL4PSf6l1XLjJBFEb0rn1dECEe55
+9OHPHjBZly0it39Fc8kCfTxKVjdpBwhC98gCyQIDAQABAoIBAEOMJB5jY9mkylH7
+QuBHYw/R8yhQ0qDS6avzCKkSXMXfm7NgYs7nfsSBRt1TFinzREqGOpW5hlHkG8Fd
+5VS03xwvp2TtqtB9F97wde/rc9EHp3oKSUV60gHcMSaxHE3HTHSHi9mNrTPyodDm
+sqouupHueHUNwvH1GdeaPli+TqH373vknnrPJENsz2dWrLlkeY3EIAud1NnFcuWV
+FLhvYybAtb9xrq11TcXZwir9/2/mxppwDT1NyQ50YVgmV8obtXhvAbV4gXad1ivx
+cTUq/Dc7qHKjttfC/wcTNS7HQmzekl2096pWNAZhOgjxdooxOf81nxk+gHF1IjtP
+LVKyZG0CgYEA13rdC+6EV8RO4+djgJ5NObOZOx9Pvq3Q5R7b8ZlccBTfK7D2lM2d
+jDcQK9up/WUH8t1a7BDMz8/NnSsYHL4SACe5NtM9XtUSMvzHXXjiCCa8NUs9Ii1C
+93eMHAKekkOALnw8cS3VkjJ99gxbF1H3qWqZ9aDTHbIhi9WbJcdbtPcCgYEAwAIx
+Whf/llcQX0ooWAw9lJP6K2rYS8wW6V6/Cp830v7v5FZlvsJvZfHNRoM7a+/pueh+
+jx+yZC+D2rtwZebWLkspsQI0KuB4SK3HvzPUqBPncT2pyg6Vv6vwQLvjC21tMvzM
+hIup52Xp9QNmUQKE2cNVl0AegG3wFwEOYCyQ1j8CgYAEVV44rTVQJoyHnNGtdoGL
+FYeRXtHVvd0jnnlB5JmtT14lnMt4tqHifgD/QM2sYOnGApmfgb78tuslrAYyHchy
+5FmfNqRXUeWpzNedk57IFy9VywuRsmNUYr0YmxzhSCY9yRXWGNvgss9BsYHreCSI
+7bHm9LMKN9jg3Qzft6CqhQKBgQCagek2x3L7hqn9FA6s84SmSAGa6IqPS/bv6jcv
+E/p3BoECLGgJfiroTRDTegzaCZ/54tXc1DPYHMgsvoJu7bdSX1d4Qf66thD04yqG
+eO3aJtIqNOWpW90y9OgLH2ZPrsmdqwHkcwLQ2xjN+eNesvk2xtHcOVOSI2V9DXOE
+/re6PwKBgQC0x6sw/egYWibdM815zRZ1onvQNm1XiyTc4XBAwD3wMGcFsRzjmEJs
+/eRNGCP3uTaixF+JueLI3bap5fouk9m2wLezrkSkUZQT6qQMQe6APBPRWqHNdWRr
+WodIiUX8toXwajlJAOZwvzUaqDrW3pIfiv9yQIHfyAaHzpnX4m9/uQ==
+-----END RSA PRIVATE KEY-----
diff --git a/test/jdk/tools/jbooster/unrelated-cert.pem b/test/jdk/tools/jbooster/unrelated-cert.pem
new file mode 100644
index 000000000..a865fe54c
--- /dev/null
+++ b/test/jdk/tools/jbooster/unrelated-cert.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDjTCCAnWgAwIBAgIUUZE/fNRyso3SrZMwXumPUplx03IwDQYJKoZIhvcNAQEL
+BQAwVjELMAkGA1UEBhMCY24xETAPBgNVBAgMCHNoYW5naGFpMREwDwYDVQQHDAhz
+aGFuZ2hhaTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMB4XDTI0
+MDYyNjEwMDc0MloXDTI1MDYyNjEwMDc0MlowVjELMAkGA1UEBhMCY24xETAPBgNV
+BAgMCHNoYW5naGFpMREwDwYDVQQHDAhzaGFuZ2hhaTEhMB8GA1UECgwYSW50ZXJu
+ZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAsAT1DkzNXE1kPiO3RZK4HnUROwa0dAaylFb5B5CxsuTSkR+j5Jl9syyoRnRf
+tu+GZ0MsA4OG5BbSxEZjiHtgEJO7FgvvxSCade0cD/OqQqMY9bnX+nhbW++JCRNc
+WcHlZODSxuQjYNdQOi/+Y4vKJhvlbHFujRpKqb6zbfehIjRTXNCCZInno2gcAV/f
+JWVT6umhTXHqH82UnsaLGYELOLrpuXAVGxu9ThCa8GInM9/rMrlk8ejSU6bx/bh9
+FajFfGIcdOa8uDFQGLiPaRg6IAncSRLruurJIWJ8CrXQSMnUUCjlHy07vNrJnnXr
+ONZdJLMDY12x0Ss2LIGuHE+rDQIDAQABo1MwUTAdBgNVHQ4EFgQUV7nqiMC46+Wp
+z+Sa+6522O+jGQ0wHwYDVR0jBBgwFoAUV7nqiMC46+Wpz+Sa+6522O+jGQ0wDwYD
+VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAb6nhPg0WBQyDKXsX0tAS
+Al11vKHrzLd3/KqAzrb78YZKmQIHb6jjwYz/S5CBuHsxq37MIGSmZlr0VMgnOTTq
+WO2KpEZBQAIAEV2JOMkSzkjhQA3Ftwon8phuEghiODW2dFLtFv+NdS4crJ4A9jFa
+XnFhQlWqA0WUr98ZZWjpCXxE+SFjY+FGvR19GCDF1iOQPSmV2fr57gxGD9R7M38L
+jgR/2TzNxR8+vVeC0V4R0wOZJsacxdJBn3XgvsJIhm3npnlWgtL1ND7cH9VVB/H7
+P2THAgyviUEbHL4LuZbIIONJPQqMwnNUAprDgcVWQG/Fgvt8mPUO/ksCs1uOGFEX
+9Q==
+-----END CERTIFICATE-----
--
2.22.0