File 0151-New-makecerts-replacement-changes-to-httpd_bench_SUI.patch of Package erlang
From b806cfd95b70e47ad13bd0cfde2754adc8d0fdd3 Mon Sep 17 00:00:00 2001
From: Dmytro Lytovchenko <dima.lytovchenko@ericsson.com>
Date: Wed, 27 Aug 2025 18:09:02 +0200
Subject: [PATCH 1/3] New makecerts replacement, changes to httpd_bench_SUITE
to make it work Remove HDLT
---
lib/inets/examples/httpd_load_test/Makefile | 127 --
.../examples/httpd_load_test/hdlt.config.skel | 20 -
lib/inets/examples/httpd_load_test/hdlt.erl | 77 -
.../examples/httpd_load_test/hdlt.sh.skel | 47 -
.../examples/httpd_load_test/hdlt_client.erl | 373 ----
.../examples/httpd_load_test/hdlt_ctrl.erl | 1527 -----------------
.../examples/httpd_load_test/hdlt_logger.erl | 141 --
.../examples/httpd_load_test/hdlt_logger.hrl | 36 -
.../httpd_load_test/hdlt_random_html.erl | 51 -
.../examples/httpd_load_test/hdlt_server.erl | 166 --
.../examples/httpd_load_test/hdlt_slave.erl | 293 ----
.../httpd_load_test/hdlt_ssl_client_cert.pem | 1 -
.../httpd_load_test/hdlt_ssl_server_cert.pem | 1 -
lib/inets/examples/httpd_load_test/modules.mk | 47 -
lib/inets/examples/subdirs.mk | 23 +-
lib/inets/test/Makefile | 24 +-
lib/inets/test/httpd_bench_SUITE.erl | 416 ++---
lib/inets/test/httpd_bench_certs.erl | 128 ++
lib/inets/test/inets.spec | 23 +-
lib/inets/test/inets_test_lib.erl | 112 +-
lib/inets/test/make_certs.erl | 533 ------
21 files changed, 453 insertions(+), 3713 deletions(-)
delete mode 100644 lib/inets/examples/httpd_load_test/Makefile
delete mode 100644 lib/inets/examples/httpd_load_test/hdlt.config.skel
delete mode 100644 lib/inets/examples/httpd_load_test/hdlt.erl
delete mode 100644 lib/inets/examples/httpd_load_test/hdlt.sh.skel
delete mode 100644 lib/inets/examples/httpd_load_test/hdlt_client.erl
delete mode 100644 lib/inets/examples/httpd_load_test/hdlt_ctrl.erl
delete mode 100644 lib/inets/examples/httpd_load_test/hdlt_logger.erl
delete mode 100644 lib/inets/examples/httpd_load_test/hdlt_logger.hrl
delete mode 100644 lib/inets/examples/httpd_load_test/hdlt_random_html.erl
delete mode 100644 lib/inets/examples/httpd_load_test/hdlt_server.erl
delete mode 100644 lib/inets/examples/httpd_load_test/hdlt_slave.erl
delete mode 120000 lib/inets/examples/httpd_load_test/hdlt_ssl_client_cert.pem
delete mode 120000 lib/inets/examples/httpd_load_test/hdlt_ssl_server_cert.pem
delete mode 100644 lib/inets/examples/httpd_load_test/modules.mk
create mode 100644 lib/inets/test/httpd_bench_certs.erl
delete mode 100644 lib/inets/test/make_certs.erl
diff --git a/lib/inets/examples/httpd_load_test/Makefile b/lib/inets/examples/httpd_load_test/Makefile
deleted file mode 100644
index 18c2414231..0000000000
--- a/lib/inets/examples/httpd_load_test/Makefile
+++ /dev/null
@@ -1,127 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# SPDX-License-Identifier: Apache-2.0
-#
-# Copyright Ericsson AB 2010-2025. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-
-include $(ERL_TOP)/make/target.mk
-
-EBIN = .
-
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-
-VSN=$(INETS_VSN)
-
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/inets-$(VSN)
-EXAMPLE_RELSYSDIR = "$(RELSYSDIR)/examples"
-HDLT_RELSYSDIR = $(EXAMPLE_RELSYSDIR)/httpd_load_test
-
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-include modules.mk
-
-ERL_FILES = $(MODULES:%=%.erl)
-
-SOURCE = $(ERL_FILES) $(INTERNAL_HRL_FILES)
-
-TARGET_FILES = \
- $(ERL_FILES:%.erl=$(EBIN)/%.$(EMULATOR))
-
-ifeq ($(TYPE),debug)
-ERL_COMPILE_FLAGS += -Ddebug -W
-endif
-ERL_COMPILE_FLAGS += +nowarn_missing_doc +nowarn_missing_spec_documented
-
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-
-include ../../src/inets_app/inets.mk
-
-ERL_COMPILE_FLAGS += \
- $(INETS_FLAGS) \
- $(INETS_ERL_COMPILE_FLAGS) \
- -I../../include
-
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-$(filter-out opt, $(TYPES)):
- @${MAKE} TYPE=$@ opt
-
-opt: $(TARGET_FILES)
-
-clean:
- rm -f $(TARGET_FILES)
- rm -f errs core *~
-
-docs:
-
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-
-release_spec: opt
- $(INSTALL_DIR) $(EXAMPLE_RELSYSDIR)
- $(INSTALL_DIR) $(HDLT_RELSYSDIR)
- $(INSTALL_DATA) $(SCRIPT_SKELETONS) $(HDLT_RELSYSDIR)
- $(INSTALL_DATA) $(CONF_SKELETONS) $(HDLT_RELSYSDIR)
- $(INSTALL_DATA) $(CERT_FILES) $(HDLT_RELSYSDIR)
- $(INSTALL_DATA) $(TARGET_FILES) $(HDLT_RELSYSDIR)
- $(INSTALL_DATA) $(ERL_FILES) $(HDLT_RELSYSDIR)
-
-
-release_docs_spec:
-
-
-# ----------------------------------------------------
-# Include dependencies
-# ----------------------------------------------------
-
-megaco_codec_transform.$(EMULATOR): megaco_codec_transform.erl
-
-megaco_codec_meas.$(EMULATOR): megaco_codec_meas.erl
-
-megaco_codec_mstone1.$(EMULATOR): megaco_codec_mstone1.erl
-
-megaco_codec_mstone2.$(EMULATOR): megaco_codec_mstone2.erl
-
-megaco_codec_mstone_lib.$(EMULATOR): megaco_codec_mstone_lib.erl
-
diff --git a/lib/inets/examples/httpd_load_test/hdlt.config.skel b/lib/inets/examples/httpd_load_test/hdlt.config.skel
deleted file mode 100644
index 640867ebac..0000000000
--- a/lib/inets/examples/httpd_load_test/hdlt.config.skel
+++ /dev/null
@@ -1,20 +0,0 @@
-%% Debug: silence | info | log | debug
-{debug, [{ctrl, info}, {proxy, silence}, {slave, silence}, {client, silence}]}.
-{server, {"/usr/local/bin", "fooserver"}}.
-%% {port, 8888}. % integer() > 0
-{server_dir, "/tmp/hdlt"}. % Absolute path
-{work_dir, "/tmp/hdlt"}. % Absolute path
-{clients,
- [
- {"/opt/local/bin", "foo"},
- {"/usr/local/bin", "bar"}
- ]
-}.
-%% {send_rate, 80}. % Max number of outstanding requests, integer() > 0
-%% {test_time, 120}. % Number of seconds,
-%% {max_nof_schedulers, 8}. % integer() >= 0
-%% {work_simulator, 10000}. % integer() > 0
-%% {data_size, {100, 500, 2}}. % {integer() > 0, integer() > 0, integer() > 0}
-%% {socket_type, ip_comm}. % ip_comm | ssl | essl | ossl
-%% {server_cert_file, "hdlt_ssl_server_cert.pem"}.
-%% {client_cert_file, "hdlt_ssl_client_cert.pem"}.
\ No newline at end of file
diff --git a/lib/inets/examples/httpd_load_test/hdlt.erl b/lib/inets/examples/httpd_load_test/hdlt.erl
deleted file mode 100644
index a148b88e21..0000000000
--- a/lib/inets/examples/httpd_load_test/hdlt.erl
+++ /dev/null
@@ -1,77 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% SPDX-License-Identifier: Apache-2.0
-%%
-%% Copyright Ericsson AB 2010-2025. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% Purpose: Main API module for the httpd load test utility
-%%----------------------------------------------------------------------
-
--module(hdlt).
-
-
-%%-----------------------------------------------------------------
-%% Public interface
-%%-----------------------------------------------------------------
-
--export([start/0, start/1, stop/0, help/0]).
-
-
-%%-----------------------------------------------------------------
-%% Start the HDLT utility
-%%-----------------------------------------------------------------
-
-start() ->
- ConfigFile = "hdlt.config",
- case file:consult(ConfigFile) of
- {ok, Config} when is_list(Config) ->
- start(Config);
- Error ->
- Error
- end.
-
-start(Config) ->
- Flag = process_flag(trap_exit, true),
- Result =
- case hdlt_ctrl:start(Config) of
- {ok, Pid} ->
- receive
- {'EXIT', Pid, normal} ->
- ok;
- {'EXIT', Pid, Reason} ->
- io:format("HDLT failed: "
- "~n ~p"
- "~n", [Reason]),
- {error, Reason}
- end;
- Error ->
- Error
- end,
- process_flag(trap_exit, Flag),
- Result.
-
-
-
-stop() ->
- hdlt_ctrl:stop().
-
-
-help() ->
- hdlt_ctrl:help().
diff --git a/lib/inets/examples/httpd_load_test/hdlt.sh.skel b/lib/inets/examples/httpd_load_test/hdlt.sh.skel
deleted file mode 100644
index ebc63c0ec4..0000000000
--- a/lib/inets/examples/httpd_load_test/hdlt.sh.skel
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/bin/sh
-
-#
-# %CopyrightBegin%
-#
-# SPDX-License-Identifier: Apache-2.0
-#
-# Copyright Ericsson AB 2010-2025. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-
-# Skeleton for a script intended to run the hdlt(N)
-# performance test.
-#
-# This test can be used for several things depending on the
-# configuration: SMP or SocketType performance tests
-#
-
-ERL_HOME=<path to otp top dir>
-INETS_HOME=$ERL_HOME/lib/erlang/lib/<inets dir>
-HDLT_HOME=$INETS_HOME/examples/httpd_load_test
-PATH=$ERL_HOME/bin:$PATH
-
-HDLT="-s hdlt start"
-STOP="-s init stop"
-
-ERL="erl \
- -noshell \
- -pa $HDLT_HOME \
- $HDLT \
- $STOP"
-
-echo $ERL
-$ERL | tee hdlt.log
-
diff --git a/lib/inets/examples/httpd_load_test/hdlt_client.erl b/lib/inets/examples/httpd_load_test/hdlt_client.erl
deleted file mode 100644
index 907cd76d57..0000000000
--- a/lib/inets/examples/httpd_load_test/hdlt_client.erl
+++ /dev/null
@@ -1,373 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% SPDX-License-Identifier: Apache-2.0
-%%
-%% Copyright Ericsson AB 2010-2025. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% Purpose: The HDLT client module.
-%% This is the traffic generator
-%%----------------------------------------------------------------------
-
--module(hdlt_client).
-
--export([
- start/1,
- stop/0,
- start_inets/0,
- start_service/1,
- release/0,
- node_info/0
- ]).
-
--export([
- proxy/1
- ]).
-
--include("hdlt_logger.hrl").
-
--define(CTRL, hdlt_ctrl).
--define(PROXY, hdlt_proxy).
-
--record(state,
- {
- mode = initial,
- send_rate,
- time,
- stop_time,
- url,
- nof_reqs = 0,
- nof_reps = 0,
- last_req,
- sizes,
- socket_type,
- cert_file
- }).
-
-
-
-start(Debug) ->
- proc_lib:start_link(?MODULE, proxy, [Debug]).
-
-stop() ->
- (catch erlang:send(?PROXY, stop)),
- ok.
-
-start_inets() ->
- ?PROXY ! start_inets.
-
-start_service(Args) ->
- ?PROXY ! {start_client, Args, self()},
- receive
- client_started ->
- %% ?LOG("client service started"),
- ok
- end.
-
-release() ->
- ?PROXY ! release.
-
-node_info() ->
- ?PROXY ! {node_info, self()},
- receive
- {node_info, NodeInfo} ->
- NodeInfo
- end.
-
-
-%% ---------------------------------------------------------------------
-%%
-%% The proxy process
-%%
-
-proxy(Debug) ->
- process_flag(trap_exit, true),
- erlang:register(?PROXY, self()),
- SName = lists:flatten(
- io_lib:format("HDLT PROXY[~p,~p]", [self(), node()])),
- ?SET_NAME(SName),
- ?SET_LEVEL(Debug),
- ?LOG("starting", []),
- Ref = await_for_controller(10),
- CtrlNode = node(Ref),
- erlang:monitor_node(CtrlNode, true),
- proc_lib:init_ack({ok, self()}),
- ?DEBUG("started", []),
- proxy_loop(Ref, CtrlNode, undefined).
-
-await_for_controller(N) when N > 0 ->
- case global:whereis_name(hdlt_ctrl) of
- Pid when is_pid(Pid) ->
- erlang:monitor(process, Pid);
- _ ->
- timer:sleep(1000),
- await_for_controller(N-1)
- end;
-await_for_controller(_) ->
- proc_lib:init_ack({error, controller_not_found, nodes()}),
- timer:sleep(500),
- init:stop().
-
-
-proxy_loop(Ref, CtrlNode, Client) ->
- ?DEBUG("await command", []),
- receive
- stop ->
- ?LOG("stop", []),
- timer:sleep(1000),
- halt();
-
- start_inets ->
- ?LOG("start the inets service framework", []),
- %% inets:enable_trace(max, "/tmp/inets-httpc-trace.log", all),
- case (catch inets:start()) of
- ok ->
- ?LOG("framework started", []),
- proxy_loop(Ref, CtrlNode, Client);
- Error ->
- ?LOG("failed starting inets service framework: "
- "~n Error: ~p", [Error]),
- timer:sleep(1000),
- halt()
- end;
-
- {start_client, Args, From} ->
- ?LOG("start client with"
- "~n Args: ~p", [Args]),
- Client2 = spawn_link(fun() -> client(Args) end),
- From ! client_started,
- proxy_loop(Ref, CtrlNode, Client2);
-
- release ->
- ?LOG("release", []),
- Client ! go,
- proxy_loop(Ref, CtrlNode, Client);
-
- {node_info, Pid} ->
- ?LOG("received requets for node info", []),
- NodeInfo = get_node_info(),
- Pid ! {node_info, NodeInfo},
- proxy_loop(Ref, CtrlNode, Client);
-
- {'EXIT', Client, normal} ->
- ?LOG("received normal exit message from client (~p)",
- [Client]),
- exit(normal);
-
- {'EXIT', Client, Reason} ->
- ?INFO("received exit message from client (~p)"
- "~n Reason: ~p", [Client, Reason]),
- %% Unexpected client termination, inform the controller and die
- global:send(hdlt_ctrl, {client_exit, Client, node(), Reason}),
- exit({client_exit, Reason});
-
- {nodedown, CtrlNode} ->
- ?LOG("received nodedown for controller node - terminate", []),
- halt();
-
- {'DOWN', Ref, process, _, _} ->
- ?INFO("received DOWN message for controller - terminate", []),
- %% The controller has terminated, dont care why, time to die
- halt()
-
- end.
-
-
-
-%% ---------------------------------------------------------------------
-%%
-%% The client process
-%%
-
-client([SocketType, CertFile, URLBase, Sizes, Time, SendRate, Debug]) ->
- SName = lists:flatten(
- io_lib:format("HDLT CLIENT[~p,~p]", [self(), node()])),
- ?SET_NAME(SName),
- ?SET_LEVEL(Debug),
- ?LOG("starting with"
- "~n SocketType: ~p"
- "~n Time: ~p"
- "~n SendRate: ~p", [SocketType, Time, SendRate]),
- httpc:set_options([{max_pipeline_length, 0}]),
- if
- (SocketType =:= ssl) orelse
- (SocketType =:= ossl) orelse
- (SocketType =:= essl) ->
- %% Ensure crypto and ssl started:
- application:start(crypto),
- ssl:start();
- true ->
- ok
- end,
- State = #state{mode = idle,
- url = URLBase,
- time = Time,
- send_rate = SendRate,
- sizes = Sizes,
- socket_type = SocketType,
- cert_file = CertFile},
- ?DEBUG("started", []),
- client_loop(State).
-
-%% The point is to first start all client nodes and then this
-%% process. Then, when they are all started, the go-ahead, go,
-%% message is sent to let them lose at the same time.
-client_loop(#state{mode = idle,
- time = Time,
- send_rate = SendRate} = State) ->
- ?DEBUG("[idle] awaiting the go command", []),
- receive
- go ->
- ?LOG("[idle] received go", []),
- erlang:send_after(Time, self(), stop),
- NewState = send_requests(State, SendRate),
- client_loop(NewState#state{mode = generating,
- nof_reqs = SendRate})
- end;
-
-%% In this mode the client is generating traffic.
-%% It will continue to do so until the stop message
-%% is received.
-client_loop(#state{mode = generating} = State) ->
- receive
- stop ->
- ?LOG("[generating] received stop", []),
- StopTime = timestamp(),
- req_reply(State),
- client_loop(State#state{mode = stopping, stop_time = StopTime});
-
- {http, {_, {{_, 200, _}, _, _}}} ->
- %% ?DEBUG("[generating] received reply - send another request", []),
- NewState = send_requests(State, 1),
- client_loop(NewState#state{nof_reps = NewState#state.nof_reps + 1,
- nof_reqs = NewState#state.nof_reqs + 1});
-
- {http, {ReqId, {error, Reason}}} ->
- ?INFO("[generating] request ~p failed: "
- "~n Reason: ~p"
- "~n NofReqs: ~p"
- "~n NofReps: ~p",
- [ReqId, Reason, State#state.nof_reqs, State#state.nof_reps]),
- exit({Reason, generating, State#state.nof_reqs, State#state.nof_reps});
-
- Else ->
- ?LOG("[generating] received unexpected message: "
- "~n~p", [Else]),
- unexpected_data(Else),
- client_loop(State)
- end;
-
-%% The client no longer issues any new requests, instead it
-%% waits for replies for all the outstanding requests to
-%% arrive.
-client_loop(#state{mode = stopping,
- time = Time,
- last_req = LastReqId} = State) ->
- receive
- {http, {LastReqId, {{_, 200, _}, _, _}}} ->
- ?DEBUG("[stopping] received reply for last request (~p)", [LastReqId]),
- time_to_complete(State),
- ok;
-
- {http, {ReqId, {{_, 200, _}, _, _}}} ->
- ?DEBUG("[stopping] received reply ~p", [ReqId]),
- client_loop(State);
-
- {http, {ReqId, {error, Reason}}} ->
- ?INFO("[stopping] request ~p failed: "
- "~n Reason: ~p"
- "~n NofReqs: ~p"
- "~n NofReps: ~p",
- [ReqId, Reason, State#state.nof_reqs, State#state.nof_reps]),
- exit({Reason, stopping, State#state.nof_reqs, State#state.nof_reps});
-
- Else ->
- ?LOG("[stopping] received unexpected message: "
- "~n~p", [Else]),
- unexpected_data(Else),
- client_loop(State)
-
- after Time ->
- ?INFO("timeout when"
- "~n Number of requests: ~p"
- "~n Number of replies: ~p",
- [State#state.nof_reqs, State#state.nof_reps]),
- exit({timeout, State#state.nof_reqs, State#state.nof_reps})
- end.
-
-req_reply(#state{nof_reqs = NofReqs, nof_reps = NofReps}) ->
- load_data({req_reply, node(), NofReqs, NofReps}).
-
-time_to_complete(#state{stop_time = StopTime}) ->
- StoppedTime = os:timestamp(),
- load_data({time_to_complete, node(), StopTime, StoppedTime}).
-
-load_data(Data) ->
- global:send(?CTRL, {load_data, Data}).
-
-unexpected_data(Else) ->
- global:send(?CTRL, {unexpected_data, Else}).
-
-
-send_requests(#state{sizes = Sizes} = State, N) ->
- send_requests(State, N, Sizes).
-
-send_requests(State, 0, Sizes) ->
- State#state{sizes = Sizes};
-send_requests(#state{socket_type = SocketType,
- cert_file = CertFile} = State, N, [Sz | Sizes]) ->
- URL = lists:flatten(io_lib:format("~s~w", [State#state.url, Sz])),
- Method = get,
- Request = {URL, []},
- HTTPOptions =
- case SocketType of
- ip_comm ->
- [];
- _ ->
- SslOpts = [{verify, 0},
- {certfile, CertFile},
- {keyfile, CertFile}],
- case SocketType of
- ssl ->
- [{ssl, SslOpts}];
- ossl ->
- [{ssl, {ossl, SslOpts}}];
- essl ->
- [{ssl, {essl, SslOpts}}]
- end
- end,
- Options = [{sync, false}],
- {ok, Ref} = httpc:request(Method, Request, HTTPOptions, Options),
- send_requests(State#state{last_req = Ref}, N-1, lists:append(Sizes, [Sz])).
-
-
-timestamp() ->
- os:timestamp().
-
-
-get_node_info() ->
- [{cpu_topology, erlang:system_info(cpu_topology)},
- {heap_type, erlang:system_info(heap_type)},
- {nof_schedulers, erlang:system_info(schedulers)},
- {otp_release, erlang:system_info(otp_release)},
- {version, erlang:system_info(version)},
- {system_version, erlang:system_info(system_version)},
- {system_architecture, erlang:system_info(system_architecture)}].
-
-
diff --git a/lib/inets/examples/httpd_load_test/hdlt_ctrl.erl b/lib/inets/examples/httpd_load_test/hdlt_ctrl.erl
deleted file mode 100644
index 6ff137be58..0000000000
--- a/lib/inets/examples/httpd_load_test/hdlt_ctrl.erl
+++ /dev/null
@@ -1,1527 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% SPDX-License-Identifier: Apache-2.0
-%%
-%% Copyright Ericsson AB 2010-2025. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% Purpose: The httpd load test (hdlt) controller/collector module,
-%% This module contains all the code of the httpd load test
-%% controller/collector. It sets up the test, starts all
-%% server and client nodes and applications and finally
-%% collects test data.
-%%----------------------------------------------------------------------
-
--module(hdlt_ctrl).
--dialyzer({no_fail_call, proxy_loop/1}).
--export([start/1, stop/0, help/0]).
-
--export([init/1, proxy/7]).
-
--include_lib("kernel/include/file.hrl").
--include("hdlt_logger.hrl").
-
--define(DEFAULT_SENDRATE, 89).
--define(DEFAULT_TEST_TIME, 120). % 2 minutes
--define(DEFAULT_PORT, 8889).
--define(TIMEOUT, 60000).
--define(DEFAULT_MAX_NOF_SCHEDULERS, 8).
--define(DEFAULT_SERVER_DIR, "/tmp/hdlt").
--define(DEFAULT_WORK_DIR, "/tmp/hdlt").
--define(SSH_PORT, 22).
--define(DEFAULT_SOCKET_TYPE, ip_comm).
--define(DEFAULT_SERVER_CERT, "hdlt_ssl_server_cert.pem").
--define(DEFAULT_CLIENT_CERT, "hdlt_ssl_client_cert.pem").
--define(SSH_CONNECT_TIMEOUT, 5000).
--define(NODE_START_TIMEOUT, 5000).
--define(LOCAL_PROXY_START_TIMEOUT, ?NODE_START_TIMEOUT * 4).
--define(DEFAULT_DEBUGS,
- [{ctrl, info}, {slave, silence}, {proxy, silence}, {client, silence}]).
--define(DEFAULT_WORK_SIM, 10000).
--define(DEFAULT_DATA_SIZE_START, 500).
--define(DEFAULT_DATA_SIZE_END, 1500).
--define(DEFAULT_DATA_SIZE_INCR, 1).
--define(DEFAULT_DATA_SIZE, {?DEFAULT_DATA_SIZE_START,
- ?DEFAULT_DATA_SIZE_END,
- ?DEFAULT_DATA_SIZE_INCR}).
-
-
-%% hdlt = httpd load test
-
--define(COLLECTOR, hdlt_ctrl).
--define(RESULTS_TAB, hdlt_results).
-
--define(CLIENT_MOD, hdlt_client).
--define(CLIENT_NODE_NAME, ?CLIENT_MOD).
-
--define(SERVER_MOD, hdlt_server).
--define(SERVER_NODE_NAME, ?SERVER_MOD).
-
--define(LOGGER, hdlt_logger).
-
-
--record(state,
- {
- url,
- test_time,
- send_rate,
- http_server,
- http_port,
- results = ?RESULTS_TAB,
- nodes,
- server_root,
- doc_root,
- server_dir,
- work_dir,
- server_conn,
- client_conns = [],
- client_mod = ?CLIENT_MOD,
- clients,
- nof_schedulers = 0,
- max_nof_schedulers,
- socket_type,
- server_cert_file,
- client_cert_file,
- debugs,
- client_sz_from,
- client_sz_to,
- client_sz_incr
- }
- ).
-
--record(proxy,
- {
- mode,
- mod,
- connection,
- channel,
- host,
- cmd,
- node_name,
- node,
- ref,
- erl_path,
- paths,
- args
- }).
-
--record(connection,
- {
- proxy,
- node,
- node_name,
- host
- }).
-
-
--record(client, {host, path, version}).
--record(server, {host, path, version}).
-
-
-start(Config) when is_list(Config) ->
- proc_lib:start_link(?MODULE, init, [Config]).
-
-stop() ->
- global:send(?COLLECTOR, stop).
-
-init(Config) ->
- %% io:format("Config: ~n~p~n", [Config]),
- case (catch do_init(Config)) of
- {ok, State} ->
- proc_lib:init_ack({ok, self()}),
- loop(State);
- {error, _Reason} = Error ->
- proc_lib:init_ack(Error),
- ok;
- {'EXIT', Reason} ->
- proc_lib:init_ack({error, Reason}),
- ok
- end.
-
-do_init(Config) ->
- %% Do not trap exit, but register ourself
- global:register_name(?COLLECTOR, self()),
-
- State = #state{},
- ets:new(State#state.results, [bag, named_table]),
-
- hdlt_logger:start(),
- global:sync(),
-
- %% Maybe enable debug
- Debugs = get_debugs(Config),
- ?SET_NAME("HDLT CTRL"),
- set_debug_level(Debugs),
-
- ?DEBUG("network info: "
- "~n Global names: ~p"
- "~n Nodes: ~p", [global:registered_names(), nodes()]),
-
- %% Read config
- ?LOG("read config", []),
- SendRate = get_send_rate(Config),
- Clients = get_clients(Config),
- TestTime = get_test_time(Config),
- Server = get_server(Config),
- Port = get_port(Config),
- ServerDir = get_server_dir(Config),
- WorkingDir = get_work_dir(Config),
- MaxNofSchedulers = get_max_nof_schedulers(Config),
- SocketType = get_socket_type(Config),
- ServerCertFile = get_server_cert_file(Config),
- ClientCertFile = get_client_cert_file(Config),
- WorkSim = get_work_sim(Config),
- {From, To, Incr} = get_data_size(Config),
-
- URL = url(Server, Port, SocketType, WorkSim),
- ServerRoot = filename:join(ServerDir, "server_root"),
- DocRoot = ServerRoot, %% Not really used in this test
-
- %% Start used applications
- ?DEBUG("ensure crypto started", []),
- application:start(crypto),
- ?DEBUG("ensure ssh started", []),
- ssh:start(),
-
- State2 = State#state{server_root = ServerRoot,
- doc_root = DocRoot,
- server_dir = ServerDir,
- work_dir = WorkingDir,
- max_nof_schedulers = MaxNofSchedulers,
- socket_type = SocketType,
- server_cert_file = ServerCertFile,
- client_cert_file = ClientCertFile,
- http_server = Server,
- http_port = Port,
- url = URL,
- test_time = TestTime,
- send_rate = SendRate,
- clients = Clients,
- debugs = Debugs,
- client_sz_from = From,
- client_sz_to = To,
- client_sz_incr = Incr},
-
- ?LOG("prepare server host", []),
- prepare_server_host(State2),
-
- ?LOG("prepare client hosts", []),
- State3 = prepare_client_hosts(State2),
-
- ?LOG("basic init done", []),
- {ok, State3}.
-
-
-loop(#state{nof_schedulers = N, max_nof_schedulers = M} = State) when N > M ->
-
- ?INFO("Starting to analyse data", []),
-
- AnalysedTab = analyse_data(State),
-
- Files = save_results_to_file(AnalysedTab, State),
- io:format("~n******************************************************"
- "~n~nResult(s) saved to: ~n~p~n", [Files]),
- clean_up(State);
-
-loop(#state{url = URL,
- test_time = TestTime,
- send_rate = SendRate,
- nof_schedulers = NofSchedulers} = State) ->
-
- {StartH, StartM, StartS} = erlang:time(),
-
- ?INFO("Performing test with ~p smp-scheduler(s): ~n"
- " It will take a minimum of: ~p seconds. ~n"
- " Start time: ~.2.0w:~.2.0w:~.2.0w",
- [NofSchedulers, round(TestTime/1000), StartH, StartM, StartS]),
-
- %% Start the server node
- %% (The local proxy, the node, the remote proxy, and the inets framework)
- State1 = start_server_node(State),
- ?DEBUG("nodes after server start: ~p", [nodes() -- [node()]]),
-
- %% Start the client node(s)
- %% (The local proxy, the node, the remote proxy, and the inets framework)
- ?LOG("start client node(s)", []),
- State2 = start_client_nodes(State1),
- ?DEBUG("nodes after client(s) start: ~p", [nodes() -- [node()]]),
-
- ?LOG("start server", []),
- start_server(State2),
-
- ?LOG("start clients", []),
- start_clients(State2, URL, TestTime, SendRate),
-
- ?LOG("release clients", []),
- release_clients(State2),
-
- ?LOG("collect data", []),
- collect_data(State2),
-
- ?LOG("stop all nodes", []),
- State3 = stop_nodes(State2),
-
- ?INFO("Test with ~p smp-scheduler(s) complete"
- "~n~n"
- "****************************************************************"
- "~n",
- [NofSchedulers]),
- loop(State3#state{nof_schedulers = NofSchedulers + 1}).
-
-
-prepare_server_host(#state{server_root = ServerRoot,
- http_server = #server{host = Host},
- socket_type = SocketType,
- server_cert_file = CertFile}) ->
- ?INFO("prepare server host ~s", [Host]),
- Opts = [{user_interaction, false},
- {silently_accept_hosts, true},
- {timeout, 2*?SSH_CONNECT_TIMEOUT},
- {connect_timeout, ?SSH_CONNECT_TIMEOUT}],
- case ssh_sftp:start_channel(Host, Opts) of
- {ok, Sftp, ConnectionRef} ->
- ?DEBUG("sftp connection established - now transfer server content",
- []),
- create_server_content(Sftp, ServerRoot, SocketType, CertFile),
- ?DEBUG("server content transferred - now close ssh connection ",
- []),
- ssh:close(ConnectionRef),
- ?DEBUG("server preparation complete ", []),
- ok;
- Error ->
- ?INFO("FAILED creating sftp channel to server host ~s: "
- "~n ~p", [Host, Error]),
- exit({failed_establishing_sftp_connection, Error})
- end.
-
-create_server_content(Sftp, ServerRoot, SocketType, CertFile) ->
- %% Create server root
- ?DEBUG("ensure existence of ~p", [ServerRoot]),
- ensure_remote_dir_exist(Sftp, ServerRoot),
-
- %% Create the server ebin dir (for the starter module)
- EBIN = filename:join(ServerRoot, "ebin"),
- ?DEBUG("make ebin dir: ~p", [EBIN]),
- maybe_create_remote_dir(Sftp, EBIN),
-
- %% Create the server ebin dir (for the starter module)
- LOG = filename:join(ServerRoot, "log"),
- ?DEBUG("make log dir: ~p", [LOG]),
- maybe_create_remote_dir(Sftp, LOG),
-
- LocalServerMod = local_server_module(),
- ?DEBUG("copy server stub/proxy module ~s", [LocalServerMod]),
- RemoteServerMod = remote_server_module(EBIN),
- {ok, ServerModBin} = file:read_file(LocalServerMod),
- ok = ssh_sftp:write_file(Sftp, RemoteServerMod, ServerModBin),
-
- LocalSlaveMod = local_slave_module(),
- ?DEBUG("copy slave module ~s", [LocalSlaveMod]),
- RemoteSlaveMod = remote_slave_module(EBIN),
- {ok, SlaveModBin} = file:read_file(LocalSlaveMod),
- ok = ssh_sftp:write_file(Sftp, RemoteSlaveMod, SlaveModBin),
-
- LocalLoggerMod = local_logger_module(),
- ?DEBUG("copy logger module ~s", [LocalLoggerMod]),
- RemoteLoggerMod = remote_logger_module(EBIN),
- {ok, LoggerModBin} = file:read_file(LocalLoggerMod),
- ok = ssh_sftp:write_file(Sftp, RemoteLoggerMod, LoggerModBin),
-
- %% Create the inets server data dir
- CGI = filename:join(ServerRoot, "cgi-bin"),
- ?DEBUG("make cgi dir: ~p", [CGI]),
- maybe_create_remote_dir(Sftp, CGI),
-
- LocalRandomMod = local_random_html_module(),
- ?DEBUG("copy random-html module ~s", [LocalRandomMod]),
- RemoteRandomMod = remote_random_html_module(EBIN),
- {ok, RandomModBin} = file:read_file(LocalRandomMod),
- ok = ssh_sftp:write_file(Sftp, RemoteRandomMod, RandomModBin),
-
- case SocketType of
- ip_comm ->
- ok;
- _ ->
- SSLDir = filename:join(ServerRoot, "ssl"),
- ?DEBUG("make conf dir: ~p", [SSLDir]),
- maybe_create_remote_dir(Sftp, SSLDir),
- ?DEBUG("copy ssl cert file ~s", [CertFile]),
- {ok, CertBin} = file:read_file(CertFile),
- RemoteCertFile = filename:join(SSLDir,
- filename:basename(CertFile)),
- ok = ssh_sftp:write_file(Sftp, RemoteCertFile, CertBin),
- ok
- end,
-
- ?DEBUG("done", []),
- ok.
-
-remote_server_module(Path) ->
- Mod = server_module(),
- filename:join(Path, Mod).
-
-local_server_module() ->
- Mod = server_module(),
- case code:where_is_file(Mod) of
- Path when is_list(Path) ->
- Path;
- _ ->
- exit({server_module_not_found, Mod})
- end.
-
-server_module() ->
- module(?SERVER_MOD).
-
-
-prepare_client_hosts(#state{work_dir = WorkDir,
- clients = Clients,
- socket_type = SocketType,
- client_cert_file = CertFile} = State) ->
- Clients2 =
- prepare_client_hosts(WorkDir, SocketType, CertFile, Clients, []),
- State#state{clients = Clients2}.
-
-prepare_client_hosts(_WorkDir, _SocketType, _CertFile, [], Acc) ->
- lists:reverse(Acc);
-prepare_client_hosts(WorkDir, SocketType, CertFile, [Client|Clients], Acc) ->
- case prepare_client_host(WorkDir, SocketType, CertFile, Client) of
- ok ->
- prepare_client_hosts(WorkDir, SocketType, CertFile, Clients,
- [Client|Acc]);
- _ ->
- prepare_client_hosts(WorkDir, SocketType, CertFile, Clients, Acc)
- end.
-
-prepare_client_host(WorkDir, SocketType, CertFile, #client{host = Host}) ->
- ?INFO("prepare client host ~s", [Host]),
- Opts = [{user_interaction, false},
- {silently_accept_hosts, true},
- {timeout, 2*?SSH_CONNECT_TIMEOUT},
- {connect_timeout, ?SSH_CONNECT_TIMEOUT}],
- case ssh_sftp:start_channel(Host, Opts) of
- {ok, Sftp, ConnectionRef} ->
- ?DEBUG("sftp connection established - now transfer client content",
- []),
- create_client_content(Sftp, WorkDir, SocketType, CertFile),
- ?DEBUG("client content transered - now close ssh connection ", []),
- ssh:close(ConnectionRef),
- ?DEBUG("client preparation complete ", []),
- ok;
- Error ->
- ?INFO("FAILED creating sftp channel to client host ~s: skipping"
- "~n ~p", [Host, Error]),
- Error
- end.
-
-create_client_content(Sftp, WorkDir, SocketType, CertFile) ->
- %% Create work dir
- ?DEBUG("ensure existence of ~p", [WorkDir]),
- ensure_remote_dir_exist(Sftp, WorkDir),
-
- %% Create the client ebin dir
- EBIN = filename:join(WorkDir, "ebin"),
- RemoteClientMod = remote_client_module(EBIN),
- ?DEBUG("make ebin dir: ~p", [EBIN]),
- maybe_create_remote_dir(Sftp, EBIN),
-
- LocalClientMod = local_client_module(),
- ?DEBUG("copy client stub/proxy module ~s", [LocalClientMod]),
- {ok, ClientModBin} = file:read_file(LocalClientMod),
- ok = ssh_sftp:write_file(Sftp, RemoteClientMod, ClientModBin),
-
- LocalSlaveMod = local_slave_module(),
- ?DEBUG("copy slave module ~s", [LocalSlaveMod]),
- RemoteSlaveMod = remote_slave_module(EBIN),
- {ok, SlaveModBin} = file:read_file(LocalSlaveMod),
- ok = ssh_sftp:write_file(Sftp, RemoteSlaveMod, SlaveModBin),
-
- LocalLoggerMod = local_logger_module(),
- ?DEBUG("copy logger module ~s", [LocalLoggerMod]),
- RemoteLoggerMod = remote_logger_module(EBIN),
- {ok, LoggerModBin} = file:read_file(LocalLoggerMod),
- ok = ssh_sftp:write_file(Sftp, RemoteLoggerMod, LoggerModBin),
-
- case SocketType of
- ip_comm ->
- ok;
- _ ->
- %% We should really store the remote path somewhere as
- %% we use it when starting the client service...
- SSLDir = filename:join(WorkDir, "ssl"),
- ?DEBUG("make ssl dir: ~p", [SSLDir]),
- maybe_create_remote_dir(Sftp, SSLDir),
- ?DEBUG("copy ssl cert file ~s", [CertFile]),
- {ok, CertBin} = file:read_file(CertFile),
- RemoteCertFile = filename:join(SSLDir,
- filename:basename(CertFile)),
- ok = ssh_sftp:write_file(Sftp, RemoteCertFile, CertBin),
- ok
- end,
-
- ?DEBUG("done", []),
- ok.
-
-remote_client_module(Path) ->
- Mod = client_module(),
- filename:join(Path, Mod).
-
-local_client_module() ->
- Mod = client_module(),
- case code:where_is_file(Mod) of
- Path when is_list(Path) ->
- Path;
- _ ->
- exit({client_module_not_found, Mod})
- end.
-
-client_module() ->
- module(?CLIENT_MOD).
-
-
-remote_slave_module(Path) ->
- Mod = slave_module(),
- filename:join(Path, Mod).
-
-local_slave_module() ->
- Mod = slave_module(),
- case code:where_is_file(Mod) of
- Path when is_list(Path) ->
- Path;
- _ ->
- exit({slave_module_not_found, Mod})
- end.
-
-slave_module() ->
- module(hdlt_slave).
-
-
-remote_logger_module(Path) ->
- Mod = logger_module(),
- filename:join(Path, Mod).
-
-local_logger_module() ->
- Mod = logger_module(),
- case code:where_is_file(Mod) of
- Path when is_list(Path) ->
- Path;
- _ ->
- exit({logger_module_not_found, Mod})
- end.
-
-logger_module() ->
- module(hdlt_logger).
-
-
-remote_random_html_module(Path) ->
- Mod = random_html_module(),
- filename:join(Path, Mod).
-
-local_random_html_module() ->
- Mod = random_html_module(),
- case code:where_is_file(Mod) of
- Path when is_list(Path) ->
- Path;
- _ ->
- exit({random_module_not_found, Mod})
- end.
-
-random_html_module() ->
- module(hdlt_random_html).
-
-
-module(Mod) ->
- Ext = string:to_lower(erlang:system_info(machine)),
- lists:flatten(io_lib:format("~w.~s", [Mod, Ext])).
-
-
-%% -----------------------------------------------------------------------
-%% - For every node created (server and client both) there is both
-%% a local and remote proxy.
-%% - The local proxy is running on the local (controller/collector) node.
-%% - The remote proxy is running on the client or server node(s).
-%% - The local (ctrl) proxy monitor the remote (server/client) proxy.
-%% - The remote (server/client) proxy monitor the local (ctrl) proxy.
-%%
-
-start_client_nodes(#state{clients = Clients,
- work_dir = WorkDir,
- debugs = Debugs} = State) ->
- Connections =
- [start_client_node(Client, WorkDir, Debugs) || Client <- Clients],
- State#state{client_conns = Connections}.
-
-start_client_node(#client{path = ErlPath, host = Host}, WorkDir, Debugs) ->
- ?INFO("start client on host ~p", [Host]),
- EbinDir = filename:join(WorkDir, "ebin"),
- start_client_node(Host, ErlPath, [EbinDir], Debugs).
-
-start_client_node(Host, ErlPath, Paths, Debugs) ->
- start_node(Host, ?CLIENT_NODE_NAME,
- ErlPath, Paths, [], ?CLIENT_MOD, Debugs).
-
-
-start_server_node(#state{http_server = #server{path = ErlPath, host = Host},
- server_root = ServerRoot,
- nof_schedulers = NofScheds,
- debugs = Debugs} = State) ->
- ?INFO("start server on host ~p", [Host]),
- CgiBinDir = filename:join(ServerRoot, "cgi-bin"),
- EbinDir = filename:join(ServerRoot, "ebin"),
- Connection =
- start_server_node(Host, ErlPath, [CgiBinDir, EbinDir],
- Debugs, NofScheds),
- State#state{server_conn = Connection}.
-
-start_server_node(Host, ErlPath, Paths, Debugs, NofScheds) ->
- Args =
- if
- NofScheds =:= 0 ->
- "-smp disable";
- true ->
- lists:flatten(io_lib:format("-smp +S ~w", [NofScheds]))
- end,
- start_node(Host, ?SERVER_NODE_NAME,
- ErlPath, Paths, Args, ?SERVER_MOD, Debugs).
-
-
-%% -----------------------------------------------------------------------
-%% - For every node created (server and client both) there is both
-%% a local and remote proxy.
-%% - The local proxy is running on the local (controller/collector) node.
-%% - The remote proxy is running on the client or server node(s).
-%% - The local (ctrl) proxy monitor the remote (server/client) proxy.
-%% - The remote (server/client) proxy monitor the local (ctrl) proxy.
-%%
-
-start_node(Host, NodeName, ErlPath, Paths, Args, Module, Debugs) ->
- %% Start the (local) proxy
- ?DEBUG("start_node -> start local proxy and remote node", []),
- ProxyDebug = proplists:get_value(proxy, Debugs, silence),
- Proxy = proxy_start(Host, NodeName, ErlPath, Paths, Args, Module,
- ProxyDebug),
-
- ?DEBUG("start_node -> local proxy started - now start node", []),
- SlaveDebug = proplists:get_value(slave, Debugs, silence),
- Node = proxy_start_node(Proxy, SlaveDebug),
-
- ?DEBUG("start_node -> sync global", []),
- global:sync(),
-
- ?DEBUG("start_node -> start remote proxy", []),
- proxy_start_remote(Proxy),
-
- ?DEBUG("start_node -> start (remote) inets framework", []),
- proxy_start_inets(Proxy),
-
- ?DEBUG("start_node -> done", []),
- #connection{proxy = Proxy, node = Node, node_name = NodeName, host = Host}.
-
-
-proxy_start(Host, NodeName, ErlPath, Paths, Args, Module, Debug) ->
- ?LOG("try starting local proxy for ~p@~s", [NodeName, Host]),
- ProxyArgs = [Host, NodeName, ErlPath, Paths, Args, Module, Debug],
- case proc_lib:start_link(?MODULE, proxy,
- ProxyArgs, ?LOCAL_PROXY_START_TIMEOUT) of
- {ok, Proxy} ->
- Proxy;
- Error ->
- exit({failed_starting_proxy, Error})
- end.
-
-proxy_start_node(Proxy, Debug) ->
- {ok, Node} = proxy_request(Proxy, {start_node, Debug}),
- Node.
-
-proxy_start_remote(Proxy) ->
- proxy_request(Proxy, start_remote_proxy).
-
-proxy_start_inets(Proxy) ->
- proxy_request(Proxy, start_inets).
-
-proxy_start_service(Proxy, Args) ->
- proxy_request(Proxy, {start_service, Args}).
-
-proxy_release(Proxy) ->
- proxy_request(Proxy, release).
-
-proxy_stop(Proxy) ->
- StopResult = proxy_request(Proxy, stop),
- ?DEBUG("proxy stop result: ~p", [StopResult]),
- StopResult.
-
-proxy_request(Proxy, Req) ->
- Ref = make_ref(),
- Proxy ! {proxy_request, Ref, self(), Req},
- receive
- {proxy_reply, Ref, Proxy, Rep} ->
- Rep
- end.
-
-proxy_reply(From, Ref, Rep) ->
- From ! {proxy_reply, Ref, self(), Rep}.
-
-proxy(Host, NodeName, ErlPath, Paths, Args, Module, Debug) ->
- process_flag(trap_exit, true),
- SName = lists:flatten(
- io_lib:format("HDLT CTRL PROXY[~p,~s,~w]",
- [self(), Host, NodeName])),
- ?SET_NAME(SName),
- ?SET_LEVEL(Debug),
- ?LOG("starting with"
- "~n Host: ~p"
- "~n NodeName: ~p"
- "~n ErlPath: ~p"
- "~n Paths: ~p"
- "~n Args: ~p"
- "~n Module: ~p", [Host, NodeName, ErlPath, Paths, Args, Module]),
- State = #proxy{mode = started,
- mod = Module,
- host = Host,
- node_name = NodeName,
- erl_path = ErlPath,
- paths = Paths,
- args = Args},
- proc_lib:init_ack({ok, self()}),
- ?DEBUG("started", []),
- proxy_loop(State).
-
-
-proxy_loop(#proxy{mode = stopping}) ->
- receive
- {proxy_request, Ref, From, stop} ->
- ?LOG("[stopping] received stop order", []),
- proxy_reply(From, Ref, ok),
- exit(normal);
-
- {'EXIT', Pid, Reason} ->
- ?INFO("[stopping] received exit message from ~p: "
- "~n Reason: ~p", [Pid, Reason]),
- exit(Reason)
-
- end;
-
-proxy_loop(#proxy{mode = started,
- host = Host,
- node_name = NodeName,
- erl_path = ErlPath,
- paths = Paths,
- args = Args} = State) ->
- receive
- {proxy_request, Ref, From, {start_node, Debug}} ->
- ?LOG("[starting] received start_node order", []),
- case hdlt_slave:start_link(Host, NodeName,
- ErlPath, Paths, Args,
- Debug) of
- {ok, Node} ->
- ?DEBUG("[starting] node ~p started - now monitor", [Node]),
- erlang:monitor_node(Node, true),
- State2 = State#proxy{mode = operational,
- node = Node},
- proxy_reply(From, Ref, {ok, Node}),
- proxy_loop(State2);
- {error, Reason} ->
- ?INFO("[starting] failed starting node: "
- "~n Reason: ~p", [Reason]),
- exit({failed_starting_node, {Host, NodeName, Reason}})
- end;
-
- {'EXIT', Pid, Reason} ->
- ?INFO("[stopping] received exit message from ~p: "
- "~n Reason: ~p", [Pid, Reason]),
- exit(Reason)
-
- end;
-
-proxy_loop(#proxy{mode = operational,
- mod = Mod,
- node = Node} = State) ->
- ?DEBUG("[operational] await command", []),
- receive
- {proxy_request, Ref, From, start_remote_proxy} ->
- ?LOG("[operational] start remote proxy", []),
- case rpc:call(Node, Mod, start, [?GET_LEVEL()]) of
- {ok, Pid} ->
- ?DEBUG("[operational] remote proxy started (~p) - "
- "create monitor", [Pid]),
- ProxyRef = erlang:monitor(process, Pid),
- ?DEBUG("[operational] monitor: ~p", [Ref]),
- proxy_reply(From, Ref, ok),
- proxy_loop(State#proxy{ref = ProxyRef});
- Error ->
- ?INFO("[operational] failed starting remote proxy"
- "~n Error: ~p", [Error]),
- ReplyReason = {failed_starting_remote_proxy,
- {Node, Error}},
- Reply = {error, ReplyReason},
- proxy_reply(From, Ref, Reply),
- exit({failed_starting_remote_proxy, {Node, Error}})
- end;
-
- {proxy_request, Ref, From, start_inets} ->
- ?INFO("[operational] start inets framework", []),
- rpc:cast(Node, Mod, start_inets, []),
- proxy_reply(From, Ref, ok),
- proxy_loop(State);
-
- {proxy_request, Ref, From, {start_service, Args}} ->
- ?INFO("[operational] start service with"
- "~n ~p", [Args]),
- case rpc:call(Node, Mod, start_service, Args) of
- ok ->
- ?DEBUG("[operational] service started", []),
- proxy_reply(From, Ref, ok),
- proxy_loop(State);
- Error ->
- ?INFO("[operational] failed starting service: "
- "~n Args. ~p"
- "~n Error: ~p", [Args, Error]),
- erlang:demonitor(State#proxy.ref, [flush]),
- Reply = {error, {failed_starting_service, Node, Error}},
- proxy_reply(From, Ref, Reply),
- exit({failed_starting_service, Node, Error})
- end;
-
- {proxy_request, Ref, From, release} ->
- ?INFO("[operational] release", []),
- rpc:call(Node, Mod, release, []),
- proxy_reply(From, Ref, ok),
- proxy_loop(State);
-
- {proxy_request, Ref, From, stop} ->
- ?INFO("[operational] received stop order", []),
- erlang:demonitor(State#proxy.ref, [flush]),
- ?DEBUG("[operational] rpc cast stop order", []),
- rpc:cast(Node, Mod, stop, []),
- %% And wait for the node death to be reported
- Reason =
- receive
- {nodedown, Node} when State#proxy.node =:= Node ->
- ok
- after 10000 ->
- ?INFO("Node did not die within expected time frame",
- []),
- {node_death_timeout, Node}
- end,
- ?DEBUG("[operational] ack stop", []),
- proxy_reply(From, Ref, Reason),
- exit(normal);
-
- {nodedown, Node} when State#proxy.node =:= Node ->
- ?INFO("[operational] received unexpected nodedoen message", []),
- exit({node_died, Node});
-
- {'DOWN', Ref, process, _, normal} when State#proxy.ref =:= Ref ->
- ?INFO("[operational] remote proxy terminated normally", []),
- proxy_loop(State#proxy{ref = undefined,
- connection = undefined,
- mode = stopping});
-
- {'DOWN', Ref, process, _, noconnection} when State#proxy.ref =:= Ref ->
- ?INFO("[operational] remote proxy terminated - no node", []),
- proxy_loop(State#proxy{ref = undefined,
- connection = undefined,
- mode = stopping});
-
- {'DOWN', Ref, process, _, Reason} when State#proxy.ref =:= Ref ->
- ?INFO("[operational] remote proxy terminated: "
- "~n Reason: ~p", [Reason]),
- exit({remote_proxy_crash, Reason});
-
- {'EXIT', Pid, Reason} ->
- ?INFO("[operational] received unexpected exit message from ~p: "
- "~n Reason: ~p", [Pid, Reason]),
- proxy_loop(State)
-
- end.
-
-
-stop_nodes(#state{server_conn = ServerConn,
- client_conns = ClientConns} = State) ->
- lists:foreach(
- fun(#connection{proxy = Proxy, node_name = NodeName, host = Host}) ->
- ?DEBUG("stop_erlang_nodes -> send stop order to local proxy ~p"
- "~n for node ~p on ~s", [Proxy, NodeName, Host]),
- proxy_stop(Proxy)
- end,
- ClientConns ++ [ServerConn]),
- ?DEBUG("stop_erlang_nodes -> sleep some to give the nodes time to die",
- []),
- timer:sleep(1000),
- ?DEBUG("stop_erlang_nodes -> and a final cleanup round", []),
- lists:foreach(fun(Node) ->
- ?INFO("try brutal stop node ~p", [Node]),
- rpc:cast(Node, erlang, halt, [])
- end,
- nodes() -- [node()]),
- ?DEBUG("stop_erlang_nodes -> done", []),
- State#state{server_conn = undefined, client_conns = []}.
-
-
-%% The nodes on which the HDLT clients run have been started previously
-start_clients(#state{client_conns = Connections,
- debugs = Debugs,
- work_dir = WorkDir,
- socket_type = SocketType,
- client_cert_file = CertFile,
- client_sz_from = From,
- client_sz_to = To,
- client_sz_incr = Incr},
- URL, TestTime, SendRate) ->
- Debug = proplists:get_value(client, Debugs, silence),
- StartClient =
- fun(#connection{host = Host} = Connection) ->
- ?DEBUG("start client on ~p", [Host]),
- start_client(Connection,
- WorkDir, SocketType, CertFile,
- URL, From, To, Incr,
- TestTime, SendRate, Debug);
- (_) ->
- ok
- end,
- lists:foreach(StartClient, Connections).
-
-start_client(#connection{proxy = Proxy},
- WorkDir, SocketType, LocalCertFile,
- URL, From, To, Incr,
- TestTime, SendRate, Debug) ->
- SSLDir = filename:join(WorkDir, "ssl"),
- CertFile = filename:join(SSLDir, filename:basename(LocalCertFile)),
- Sizes = randomized_sizes(From, To, Incr),
- Args = [SocketType, CertFile, URL, Sizes, TestTime, SendRate, Debug],
- proxy_start_service(Proxy, [Args]).
-
-release_clients(#state{client_conns = Connections}) ->
- ReleaseClient =
- fun(#connection{proxy = Proxy,
- host = Host}) ->
- ?DEBUG("release client on ~p", [Host]),
- proxy_release(Proxy);
- (_) ->
- ok
- end,
- lists:foreach(ReleaseClient, Connections).
-
-
-start_server(#state{server_conn = #connection{proxy = Proxy},
- http_port = Port,
- server_root = ServerRoot,
- doc_root = DocRoot,
- socket_type = SocketType,
- server_cert_file = CertFile}) ->
-
- HttpdConfig =
- httpd_config(Port, "hdlt", ServerRoot, DocRoot, SocketType, CertFile),
- ?LOG("start the httpd inets service with config: "
- "~n ~p", [HttpdConfig]),
- proxy_start_service(Proxy, [HttpdConfig]),
- ?DEBUG("start_server -> done", []),
- ok.
-
-
-httpd_config(Port, ServerName, ServerRoot, DocRoot,
- SocketType, LocalCertFile) ->
- LogDir = filename:join(ServerRoot, "log"),
- ErrorLog = filename:join(LogDir, "error_log"),
- TransferLog = filename:join(LogDir, "access_log"),
-
- SSL =
- case SocketType of
- ip_comm ->
- [];
- _ -> % ssl
- SSLDir = filename:join(ServerRoot, "ssl"),
- CertFile =
- filename:join(SSLDir, filename:basename(LocalCertFile)),
- [
- {ssl_certificate_file, CertFile},
- {ssl_certificate_key_file, CertFile},
- {ssl_verify_client, 0}
- ]
- end,
- [{port, Port},
- {server_name, ServerName},
- {server_root, ServerRoot},
- {document_root, DocRoot},
- {error_log, ErrorLog},
- {error_log_format, pretty},
- {transfer_log, TransferLog},
- {socket_type, SocketType},
- {max_clients, 10000},
- {modules, [mod_alias, mod_auth, mod_esi, mod_actions, mod_cgi,
- mod_dir, mod_get, mod_head, mod_log, mod_disk_log]},
- {script_alias, {"/cgi-bin", filename:join(ServerRoot, "cgi-bin")}},
- {erl_script_alias, {"/cgi-bin", [hdlt_random_html]}},
- {erl_script_timeout, 120000} | SSL].
-
-
-clean_up(#state{server_root = ServerRoot,
- work_dir = WorkDir,
- http_server = #server{host = Host},
- clients = Clients}) ->
- ?DEBUG("begin server cleanup", []),
- server_clean_up(ServerRoot, WorkDir, Host),
- ?DEBUG("begin client cleanup", []),
- clients_clean_up(WorkDir, Clients),
- ?DEBUG("cleanup done", []),
- ok.
-
-server_clean_up(ServerRoot, WorkDir, Host) ->
- ?DEBUG("server cleanup - create sftp channel", []),
- {ok, Sftp, ConnectionRef} =
- ssh_sftp:start_channel(Host, [{user_interaction, false},
- {silently_accept_hosts, true}]),
- ?DEBUG("server cleanup - delete ~p dirs", [ServerRoot]),
- del_dirs(Sftp, ServerRoot),
- ?DEBUG("server cleanup - delete ~p dirs", [WorkDir]),
- del_dirs(Sftp, WorkDir),
- ?DEBUG("server cleanup - close sftp channel", []),
- ssh:close(ConnectionRef).
-
-clients_clean_up(_WorkDir, []) ->
- ok;
-clients_clean_up(WorkDir, [Client|Clients]) ->
- client_clean_up(WorkDir, Client),
- clients_clean_up(WorkDir, Clients).
-
-client_clean_up(WorkDir, #client{host = Host}) ->
- ?DEBUG("client cleanup - create sftp channel to ~p", [Host]),
- {ok, Sftp, ConnectionRef} =
- ssh_sftp:start_channel(Host, [{user_interaction, false},
- {silently_accept_hosts, true}]),
- ?DEBUG("client cleanup - delete ~p dirs", [WorkDir]),
- del_dirs(Sftp, WorkDir),
- ?DEBUG("client cleanup - close sftp channel", []),
- ssh:close(ConnectionRef).
-
-
-del_dirs(Sftp, Dir) ->
- case ssh_sftp:list_dir(Sftp, Dir) of
- {ok, []} ->
- ssh_sftp:del_dir(Sftp, Dir);
- {ok, Files} ->
- Files2 = [F || F <- Files, (F =/= "..") andalso (F =/= ".")],
- lists:foreach(fun(File) when ((File =/= "..") andalso
- (File =/= ".")) ->
- FullPath = filename:join(Dir, File),
- case ssh_sftp:read_file_info(Sftp,
- FullPath) of
- {ok, #file_info{type = directory}} ->
- del_dirs(Sftp, FullPath),
- ssh_sftp:del_dir(Sftp, FullPath);
- {ok, _} ->
- ssh_sftp:delete(Sftp, FullPath)
- end
- end, Files2);
- _ ->
- ok
- end.
-
-collect_data(#state{clients = Clients} = State) ->
- N = length(Clients),
- collect_req_reply(N, State),
- collect_time(N, State).
-
-collect_req_reply(0, _State) ->
- ?DEBUG("all reply data collected", []),
- ok;
-collect_req_reply(N, #state{nof_schedulers = NofScheduler,
- results = Db,
- client_conns = Conns} = State) ->
- ?DEBUG("await reply data from ~p client(s)", [N]),
- receive
- {load_data,
- {req_reply, Client, NoRequests, NoReplys}} ->
- ?DEBUG("received req_reply load-data from client ~p: "
- "~n Number of requests: ~p"
- "~n Number of replies: ~p",
- [Client, NoRequests, NoReplys]),
- ets:insert(Db, {{NofScheduler, Client},
- {req_reply, NoRequests, NoReplys}});
- stop ->
- ?INFO("received stop", []),
- exit(self(), stop);
-
- {client_exit, Client, Node, Reason} ->
- ?INFO("Received unexpected client exit from ~p on node ~p "
- "while collecting replies: "
- "~n ~p", [Client, Node, Reason]),
- case lists:keysearch(Node, #connection.node, Conns) of
- {value, Conn} ->
- ?LOG("Found problem connection: "
- "~n ~p", [Conn]),
- exit({unexpected_client_exit, Reason});
- false ->
- collect_req_reply(N, State)
- end
- end,
- collect_req_reply(N-1, State).
-
-collect_time(0, _State) ->
- ?DEBUG("all time data collected", []),
- ok;
-collect_time(N, #state{nof_schedulers = NofScheduler,
- results = Db,
- client_conns = Conns} = State) ->
- ?DEBUG("await time data from ~p clients", [N]),
- receive
- {load_data,
- {time_to_complete, Client, StopTime, LastResponseTime}} ->
- ?LOG("received time load-data from client ~p: "
- "~n Time of stop: ~p"
- "~n Time of last response: ~p",
- [Client, StopTime, LastResponseTime]),
- ets:insert(Db, {{NofScheduler, Client},
- {time, StopTime, LastResponseTime}});
- stop ->
- ?INFO("received stop while collecting data, when N = ~p", [N]),
- exit(self(), stop);
-
- {client_exit, Client, Node, Reason} ->
- ?INFO("Received unexpected exit from client ~p on node ~p "
- "while collecting time data: "
- "~n ~p", [Client, Node, Reason]),
- case lists:keysearch(Node, #connection.node, Conns) of
- {value, Conn} ->
- ?LOG("Found problem connection: "
- "~n ~p", [Conn]),
- exit({unexpected_client_exit, Reason});
- false ->
- collect_req_reply(N, State)
- end;
-
- Else -> %%% Something is wrong!
- ?INFO("RECEIVED UNEXPECTED MESSAGE WHILE COLLECTING TIME DATA: "
- "~n ~p", [Else]),
- collect_time(N, State)
- end,
- collect_time(N-1, State).
-
-analyse_data(#state{results = Db,
- max_nof_schedulers = MaxNofSchedulers,
- test_time = MicroSec}) ->
- Tab = ets:new(analysed_results, [set]),
- lists:foreach(fun(NofSchedulers) ->
- Result = analyse(NofSchedulers, Db, MicroSec),
- ets:insert(Tab, Result)
- end, [N || N <- lists:seq(0, MaxNofSchedulers)]),
- Tab.
-
-
-no_requests_replys(NoSchedulers, Tab) ->
- NoRequests =
- ets:select(Tab, [{{{NoSchedulers,'_'},{req_reply, '$1', '_'}},
- [],['$$']}]),
- NoReplys =
- ets:select(Tab, [{{{NoSchedulers, '_'}, {req_reply, '_', '$1'}},
- [], ['$$']}]),
-
- {lists:sum(lists:append(NoRequests)),
- lists:sum(lists:append(NoReplys))}.
-
-max_time_to_final_response(NofSchedulers, Tab) ->
- Candidates =
- ets:select(Tab, [{{{NofSchedulers, '_'}, {time, '$1', '$2'}},
- [], ['$$']}]),
-
- NewCandidates = lists:map(
- fun([StopTime, LastTime]) ->
- round(
- timer:now_diff(LastTime, StopTime) / 100000)/10
- end, Candidates),
-
- lists:max(NewCandidates).
-
-
-analyse(NofSchedulers, Db, TestTime) ->
- Sec = TestTime / 1000,
- {NoRequests, NoReplys} = no_requests_replys(NofSchedulers, Db),
- {NofSchedulers, round(NoReplys / Sec), NoRequests,
- max_time_to_final_response(NofSchedulers, Db)}.
-
-
-save_results_to_file(AnalysedTab,
- #state{socket_type = SocketType,
- http_server = #server{host = Server},
- max_nof_schedulers = MaxNofSchedulers}) ->
- FileName = fun(Post) ->
- File =
- lists:flatten(
- io_lib:format("~s_~w_~s",
- [Server, SocketType, Post])),
- filename:join("./", File)
- end,
- Reps = FileName("replys_per_sec.txt"),
- Reqs = FileName("total_requests.txt"),
- Decay = FileName("decay_time.txt"),
-
- [FdReps, FdReqs, FdDecay] =
- lists:map(fun(File) ->
- {ok, Fd} = file:open(File, [write]),
- Fd
- end, [Reps, Reqs, Decay]),
- lists:foreach(fun(NofSchedulers) ->
- save_result_to_file(NofSchedulers,
- FdReps, FdReqs,
- FdDecay, AnalysedTab)
- end, [N || N <- lists:seq(0, MaxNofSchedulers)]),
- [Reps, Reqs, Decay].
-
-save_result_to_file(NofSchedulers,
- FdReps, FdReqs, FdDecay, AnalysedTab) ->
-
- [{NofSchedulers, NofRepsPerSec, NofReqs, MaxFinalResponseTime}] =
- ets:lookup(AnalysedTab, NofSchedulers),
-
- file:write(FdReps, io_lib:format("~p,~p~n",
- [NofRepsPerSec, NofSchedulers])),
- file:write(FdReqs, io_lib:format("~p,~p~n",
- [NofReqs, NofSchedulers])),
- file:write(FdDecay, io_lib:format("~p,~p~n", [MaxFinalResponseTime,
- NofSchedulers])).
-
-
-help() ->
- io:format("hdlt:start(Options). Where options:~n "
- " ~n~p~n~n hdlt:start([]). -> hdlt:start(~p)~n~n",
- [[{send_rate, "integer()",
- "Number of outstanding requests that a client "
- "should have during the test to create a load situation."},
- {clients, "[{path(), host()}]", "Paths to erlang and names of hosts to run clients on."},
- {test_time, "{hours(), mins(), sec()}",
- "How long the test should be run."},
- {server, "{path(), host()}", "Path to erl and name of host to run the HTTP-server on."},
- {port, "port()", "The port that the HTTP-server should use."},
- {server_dir, "dir()", "The directory where the HTTP server "
- " stores its contents and configuration."},
- {work_dir, "dir()", "Path on the computer, where the test "
- "is run, to a directory where the results can be saved."},
- {max_no_schedulers, "integer()",
- "Max number of schedulers to run."},
- {socket_type, "Httpd configuration option socket_type"}],
- defaults()]).
-
-
-defaults() ->
- [{send_rate, ?DEFAULT_SENDRATE},
- %% {clients, []},
- {test_time, ?DEFAULT_TEST_TIME},
- %% {server, ?DEFAULT_SERVER},
- {port, ?DEFAULT_PORT},
- {server_dir, ?DEFAULT_SERVER_DIR},
- {work_dir, ?DEFAULT_WORK_DIR},
- {max_nof_schedulers, ?DEFAULT_MAX_NOF_SCHEDULERS},
- {socket_type, ?DEFAULT_SOCKET_TYPE}].
-
-
-get_debugs(Config) ->
- ?DEBUG("get debugs", []),
- Debugs = proplists:get_value(debug, Config, ?DEFAULT_DEBUGS),
- verify_debugs(Debugs),
- Debugs.
-
-verify_debugs([]) ->
- ok;
-verify_debugs([{Tag, Debug}|Debugs]) ->
- verify_debug(Tag, Debug),
- verify_debugs(Debugs).
-
-verify_debug(Tag, Debug) ->
- case lists:member(Tag, [ctrl, proxy, slave, client]) of
- true ->
- ok;
- false ->
- exit({bad_debug_tag, Tag})
- end,
- case lists:member(Debug, [silence, info, log, debug]) of
- true ->
- ok;
- false ->
- exit({bad_debug_level, Debug})
- end.
-
-get_send_rate(Config) ->
- ?DEBUG("get send_rate", []),
- case proplists:get_value(send_rate, Config, ?DEFAULT_SENDRATE) of
- SendRate when is_integer(SendRate) andalso (SendRate > 0) ->
- SendRate;
- BadSendRate ->
- exit({bad_sendrate, BadSendRate})
- end.
-
-
-get_clients(Config) ->
- ?DEBUG("get clients", []),
- case proplists:get_value(clients, Config, undefined) of
- undefined ->
- missing_mandatory_config(clients);
- Clients when is_list(Clients) andalso (length(Clients) > 0) ->
- case [#client{path = Path, host = Host} ||
- {Path, Host} <- Clients] of
- Clients2 when (length(Clients2) > 0) ->
- Clients2;
- _ ->
- exit({bad_clients, Clients})
- end;
-
- BadClients ->
- exit({bad_clients, BadClients})
-
- end.
-
-get_server(Config) ->
- ?DEBUG("get server", []),
- case proplists:get_value(server, Config) of
- {Path, Host} when is_list(Path) andalso is_list(Host) ->
- #server{path = Path, host = Host};
- undefined ->
- missing_mandatory_config(server)
- end.
-
-get_server_dir(Config) ->
- ?DEBUG("get server_dir", []),
- get_dir(server_dir, Config, ?DEFAULT_SERVER_DIR).
-
-get_work_dir(Config) ->
- ?DEBUG("get work_dir", []),
- get_dir(work_dir, Config, ?DEFAULT_WORK_DIR).
-
-get_dir(Key, Config, Default) ->
- Dir = proplists:get_value(Key, Config, Default),
- ensure_absolute(Dir),
- Dir.
-
-ensure_absolute(Path) ->
- case filename:pathtype(Path) of
- absolute ->
- ok;
- PathType ->
- exit({bad_pathtype, Path, PathType})
- end.
-
-get_port(Config) ->
- ?DEBUG("get port", []),
- case proplists:get_value(port, Config, ?DEFAULT_PORT) of
- Port when is_integer(Port) andalso (Port > 0) ->
- Port;
- BadPort ->
- exit({bad_port, BadPort})
- end.
-
-get_socket_type(Config) ->
- ?DEBUG("get socket_type", []),
- case proplists:get_value(socket_type, Config, ?DEFAULT_SOCKET_TYPE) of
- SocketType when ((SocketType =:= ip_comm) orelse
- (SocketType =:= ssl) orelse
- (SocketType =:= essl) orelse
- (SocketType =:= ossl)) ->
- SocketType;
- BadSocketType ->
- exit({bad_socket_type, BadSocketType})
- end.
-
-get_test_time(Config) ->
- ?DEBUG("get test_time", []),
- case proplists:get_value(test_time, Config, ?DEFAULT_TEST_TIME) of
- Seconds when is_integer(Seconds) andalso (Seconds > 0) ->
- timer:seconds(Seconds);
- BadTestTime ->
- exit({bad_test_time, BadTestTime})
- end.
-
-get_max_nof_schedulers(Config) ->
- ?DEBUG("get max_nof_schedulers", []),
- case proplists:get_value(max_nof_schedulers,
- Config,
- ?DEFAULT_MAX_NOF_SCHEDULERS) of
- MaxNofScheds when (is_integer(MaxNofScheds) andalso
- (MaxNofScheds >= 0)) ->
- MaxNofScheds;
- BadMaxNofScheds ->
- exit({bad_max_nof_schedulers, BadMaxNofScheds})
- end.
-
-
-get_server_cert_file(Config) ->
- ?DEBUG("get server cert file", []),
- get_cert_file(server_cert_file, ?DEFAULT_SERVER_CERT, Config).
-
-get_client_cert_file(Config) ->
- ?DEBUG("get client cert file", []),
- get_cert_file(client_cert_file, ?DEFAULT_CLIENT_CERT, Config).
-
-get_cert_file(Tag, DefaultCertFileName, Config) ->
- LibDir = code:lib_dir(inets),
- HdltDir = filename:join(LibDir, "examples/httpd_load_test"),
- DefaultCertFile = filename:join(HdltDir, DefaultCertFileName),
- case proplists:get_value(Tag, Config, DefaultCertFile) of
- F when is_list(F) ->
- case file:read_file_info(F) of
- {ok, #file_info{type = regular}} ->
- F;
- {ok, #file_info{type = Type}} ->
- exit({wrong_file_type, Tag, F, Type});
- {error, Reason} ->
- exit({failed_readin_file_info, Tag, F, Reason})
- end;
- BadFile ->
- exit({bad_cert_file, Tag, BadFile})
- end.
-
-
-get_work_sim(Config) ->
- ?DEBUG("get work_sim", []),
- case proplists:get_value(work_simulator, Config, ?DEFAULT_WORK_SIM) of
- WS when is_integer(WS) andalso (WS > 0) ->
- WS;
- BadWS ->
- exit({bad_work_simulator, BadWS})
- end.
-
-
-get_data_size(Config) ->
- ?DEBUG("get data_size", []),
- case proplists:get_value(data_size, Config, ?DEFAULT_DATA_SIZE) of
- {From, To, Incr} = DS when (is_integer(From) andalso
- is_integer(To) andalso
- is_integer(Incr) andalso
- (To > From) andalso
- (From > 0) andalso
- (Incr > 0)) ->
- DS;
- {From, To} when (is_integer(From) andalso
- is_integer(To) andalso
- (To > From) andalso
- (From > 0)) ->
- {From, To, ?DEFAULT_DATA_SIZE_INCR};
- BadDS ->
- exit({bad_data_size, BadDS})
- end.
-
-
-url(#server{host = Host}, Port, SocketType, WorkSim) ->
- Scheme =
- case SocketType of
- ip_comm ->
- "http";
- _ -> %% SSL
- "https"
- end,
- lists:flatten(
- io_lib:format("~s://~s:~w/cgi-bin/hdlt_random_html:page?~w:",
- [Scheme, Host, Port, WorkSim])).
-
-
-missing_mandatory_config(Missing) ->
- exit({missing_mandatory_config, Missing}).
-
-
-ensure_remote_dir_exist(Sftp, Path0) ->
- case filename:split(Path0) of
- [Root, Dir | Rest] ->
- %% We never accept creating the root directory,
- %% or the next level, so these *must* exist:
- Path = filename:join(Root, Dir),
- case ssh_sftp:read_file_info(Sftp, Path) of
- {ok, #file_info{type = directory}} ->
- ensure_remote_dir_exist(Sftp, Path, Rest);
- {ok, #file_info{type = Type}} ->
- ?INFO("Not a dir: ~p (~p)", [Path, Type]),
- exit({not_a_dir, Path, Type});
- {error, Reason} ->
- ?INFO("Failed reading file info for ~p: ~p",
- [Path, Reason]),
- exit({failed_reading_file_info, Path, Reason})
- end;
- BadSplit ->
- ?INFO("Bad remote dir path: ~p -> ~p", [Path0, BadSplit]),
- exit({bad_dir, Path0})
- end.
-
-ensure_remote_dir_exist(_Sftp, _Dir, []) ->
- ok;
-ensure_remote_dir_exist(Sftp, Path, [Dir|Rest]) ->
- NewPath = filename:join(Path, Dir),
- case ssh_sftp:read_file_info(Sftp, NewPath) of
- {ok, #file_info{type = directory}} ->
- ensure_remote_dir_exist(Sftp, NewPath, Rest);
- {ok, #file_info{type = Type}} ->
- %% Exist, but is not a dir
- ?INFO("Not a dir: ~p (~p)", [NewPath, Type]),
- exit({not_a_dir, NewPath, Type});
- {error, Reason} ->
- %% This *could* be because the dir does not exist,
- %% but it could also be some other error.
- %% As usual, the error reason of the sftp is
- %% a pease of crap, so we cannot use the
- %% error reason.
- %% The simplest way to test this is to simply
- %% try to create the directory, since we should
- %% ensure its existence anyway..
- case ssh_sftp:make_dir(Sftp, NewPath) of
- ok ->
- ensure_remote_dir_exist(Sftp, NewPath, Rest);
- _ ->
- ?INFO("Failed reading file info for ~p: ~p",
- [Dir, Reason]),
- exit({failed_reading_file_info, NewPath, Reason})
- end
- end.
-
-maybe_create_remote_dir(Sftp, Dir) ->
- case ssh_sftp:read_file_info(Sftp, Dir) of
- {ok, #file_info{type = directory}} ->
- ok;
- {ok, #file_info{type = Type}} ->
- %% Exist, but is not a dir
- ?INFO("Not a dir: ~p (~p)", [Dir, Type]),
- exit({not_a_dir, Dir, Type});
- {error, Reason} ->
- %% Assume dir noes not exist...
- case ssh_sftp:make_dir(Sftp, Dir) of
- ok ->
- ok;
- _ ->
- ?INFO("Failed reading file info for ~p: ~p",
- [Dir, Reason]),
- exit({failed_reading_file_info, Dir, Reason})
- end
- end.
-
-
-set_debug_level(Debugs) ->
- Debug = proplists:get_value(ctrl, Debugs, silence),
- ?SET_LEVEL(Debug).
-
-
-%% Generates a list of numbers between A and B, such that
-%% there is exact one number between A and B and then
-%% randomizes that list.
-
-
-randomized_sizes(From, To, Incr) ->
- L = lists:seq(From, To, Incr),
- Len = length(L),
- randomized_sizes2(L, 0, Len-1).
-
-randomized_sizes2(L, N, Len) when N >= Len ->
- L;
-randomized_sizes2(L, N, Len) ->
- SplitWhere = rand:uniform(Len),
- {A, B} = lists:split(SplitWhere, L),
- randomized_sizes2(B ++ A, N+1, Len).
diff --git a/lib/inets/examples/httpd_load_test/hdlt_logger.erl b/lib/inets/examples/httpd_load_test/hdlt_logger.erl
deleted file mode 100644
index 8bbd53e0de..0000000000
--- a/lib/inets/examples/httpd_load_test/hdlt_logger.erl
+++ /dev/null
@@ -1,141 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% SPDX-License-Identifier: Apache-2.0
-%%
-%% Copyright Ericsson AB 2010-2025. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%----------------------------------------------------------------------
-%% Purpose: This is a simple logger utility for the HDLT toolkit.
-%% It assumesd that the debug level and the "name" of the
-%% logging entity has been put in process environment
-%% (using the set_level and set_name functions respectively).
-%%----------------------------------------------------------------------
-
-%%
-
--module(hdlt_logger).
-
--export([
- start/0,
- set_level/1, get_level/0, set_name/1,
- info/2, log/2, debug/2
- ]).
-
--export([logger/1]).
-
--define(LOGGER, ?MODULE).
--define(MSG, hdlt_logger_msg).
--define(LEVEL, hdlt_logger_level).
--define(NAME, hdlt_logger_name).
--define(INFO_STR, "INFO").
--define(LOG_STR, "LOG ").
--define(DEBUG_STR, "DBG ").
-
-
-start() ->
- Self = self(),
- proc_lib:start(?MODULE, logger, [Self]).
-
-set_name(Name) when is_list(Name) ->
- put(?NAME, Name),
- ok.
-
-get_level() ->
- get(?LEVEL).
-
-set_level(Level) ->
- case lists:member(Level, [silence, info, log, debug]) of
- true ->
- put(?LEVEL, Level),
- ok;
- false ->
- erlang:error({bad_debug_level, Level})
- end.
-
-
-info(F, A) ->
-%% io:format("info -> " ++ F ++ "~n", A),
- do_log(info, get(?LEVEL), F, A).
-
-log(F, A) ->
-%% io:format("log -> " ++ F ++ "~n", A),
- do_log(log, get(?LEVEL), F, A).
-
-debug(F, A) ->
-%% io:format("debug -> " ++ F ++ "~n", A),
- do_log(debug, get(?LEVEL), F, A).
-
-
-logger(Parent) ->
- global:register_name(?LOGGER, self()),
- Ref = erlang:monitor(process, Parent),
- proc_lib:init_ack(self()),
- logger_loop(Ref).
-
-logger_loop(Ref) ->
- receive
- {?MSG, F, A} ->
- io:format(F, A),
- logger_loop(Ref);
- {'DOWN', Ref, process, _Object, _Info} ->
- %% start the stop timer
- erlang:send_after(timer:seconds(5), self(), stop),
- logger_loop(undefined);
- stop ->
- global:unregister_name(?LOGGER),
- ok
- end.
-
-
-formated_timestamp() ->
- {Date, Time} = erlang:localtime(),
- {YYYY,MM,DD} = Date,
- {Hour,Min,Sec} = Time,
- FormatDate =
- io_lib:format("~.4w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w",
- [YYYY,MM,DD,Hour,Min,Sec]),
- lists:flatten(FormatDate).
-
-do_log(_, silence, _, _) ->
- ok;
-do_log(info, info, F, A) ->
- do_log(?INFO_STR, F, A);
-do_log(info, log, F, A) ->
- do_log(?INFO_STR, F, A);
-do_log(log, log, F, A) ->
- do_log(?LOG_STR, F, A);
-do_log(info, debug, F, A) ->
- do_log(?INFO_STR, F, A);
-do_log(log, debug, F, A) ->
- do_log(?LOG_STR, F, A);
-do_log(debug, debug, F, A) ->
- do_log(?DEBUG_STR, F, A);
-do_log(_, _, _F, _A) ->
- ok.
-
-do_log(SEV, F, A) ->
- Name =
- case get(?NAME) of
- L when is_list(L) ->
- L;
- _ ->
- "UNDEFINED"
- end,
- Msg = {?MSG, "~s ~s [~s] " ++ F ++ "~n",
- [SEV, Name, formated_timestamp() | A]},
- (catch global:send(?LOGGER, Msg)).
diff --git a/lib/inets/examples/httpd_load_test/hdlt_logger.hrl b/lib/inets/examples/httpd_load_test/hdlt_logger.hrl
deleted file mode 100644
index 6fbe9bd393..0000000000
--- a/lib/inets/examples/httpd_load_test/hdlt_logger.hrl
+++ /dev/null
@@ -1,36 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% SPDX-License-Identifier: Apache-2.0
-%%
-%% Copyright Ericsson AB 2010-2025. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--ifndef(hdlt_logger_hrl).
--define(hdlt_logger_hrl, true).
-
-%% Various log macros
--define(SET_LEVEL(N), hdlt_logger:set_level(N)).
--define(GET_LEVEL(), hdlt_logger:get_level()).
--define(SET_NAME(N), hdlt_logger:set_name(N)).
-
--define(INFO(F, A), hdlt_logger:info(F, A)).
--define(LOG(F, A), hdlt_logger:log(F, A)).
--define(DEBUG(F, A), hdlt_logger:debug(F, A)).
-
--endif. % -ifdef(hdlt_logger_hrl).
diff --git a/lib/inets/examples/httpd_load_test/hdlt_random_html.erl b/lib/inets/examples/httpd_load_test/hdlt_random_html.erl
deleted file mode 100644
index 2f2a23f82d..0000000000
--- a/lib/inets/examples/httpd_load_test/hdlt_random_html.erl
+++ /dev/null
@@ -1,51 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% SPDX-License-Identifier: Apache-2.0
-%%
-%% Copyright Ericsson AB 2010-2025. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(hdlt_random_html).
--export([page/3]).
-
-page(SessionID, _Env, Input) ->
- [WorkSimStr, SzSimStr] = string:tokens(Input, [$:]),
- WorkSim = list_to_integer(WorkSimStr),
- SzSim = list_to_integer(SzSimStr),
- mod_esi:deliver(SessionID, "Content-Type:text/html\r\n\r\n"),
- mod_esi:deliver(SessionID, start("Random test page")),
- mod_esi:deliver(SessionID, content(WorkSim, SzSim)),
- mod_esi:deliver(SessionID, stop()),
- ok.
-
-start(Title) ->
- "<HTML>
-<HEAD>
-<TITLE>" ++ Title ++ "</TITLE>
- </HEAD>
-<BODY>\n".
-
-stop() ->
- "</BODY>
-</HTML>
-".
-
-content(WorkSim, SzSim) ->
- lists:sort([rand:uniform(X) || X <- lists:seq(1, WorkSim)]),
- lists:flatten(lists:duplicate(SzSim, "Dummy data ")).
diff --git a/lib/inets/examples/httpd_load_test/hdlt_server.erl b/lib/inets/examples/httpd_load_test/hdlt_server.erl
deleted file mode 100644
index a46c0b01b0..0000000000
--- a/lib/inets/examples/httpd_load_test/hdlt_server.erl
+++ /dev/null
@@ -1,166 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% SPDX-License-Identifier: Apache-2.0
-%%
-%% Copyright Ericsson AB 2010-2025. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% Purpose: The HDLT server module.
-%% This is just a stub, making future expansion easy.
-%% All code in this module is executed in the local node!
-%%----------------------------------------------------------------------
-
--module(hdlt_server).
-
--export([start/1, stop/0, start_inets/0, start_service/1]).
-
--export([proxy/1]).
-
--include_lib("kernel/include/file.hrl").
--include("hdlt_logger.hrl").
-
-
--define(PROXY, hdlt_proxy).
-
-
-%% This function is used to start the proxy process
-%% This function is called *after* the nodes has been
-%% "connected" with the controller/collector node.
-
-start(Debug) ->
- proc_lib:start(?MODULE, proxy, [Debug]).
-
-stop() ->
- ?PROXY ! stop.
-
-start_inets() ->
- ?PROXY ! start_inets.
-
-start_service(Config) ->
- ?PROXY ! {server_start, Config, self()},
- receive
- {server_start_result, Result} ->
- Result
- after 15000 ->
- {error, timeout}
- end.
-
-
-proxy(Debug) ->
- process_flag(trap_exit, true),
- erlang:register(?PROXY, self()),
- ?SET_NAME("HDLT PROXY"),
- ?SET_LEVEL(Debug),
- ?LOG("starting", []),
- Ref = await_for_controller(10),
- CtrlNode = node(Ref),
- erlang:monitor_node(CtrlNode, true),
- proc_lib:init_ack({ok, self()}),
- ?DEBUG("started", []),
- proxy_loop(Ref, CtrlNode).
-
-await_for_controller(N) when N > 0 ->
- case global:whereis_name(hdlt_ctrl) of
- Pid when is_pid(Pid) ->
- erlang:monitor(process, Pid);
- _ ->
- timer:sleep(1000),
- await_for_controller(N-1)
- end;
-await_for_controller(_) ->
- proc_lib:init_ack({error, controller_not_found, nodes()}),
- timer:sleep(500),
- halt().
-
-
-proxy_loop(Ref, CtrlNode) ->
- ?DEBUG("await command", []),
- receive
- stop ->
- ?LOG("received stop", []),
- halt();
-
- start_inets ->
- ?LOG("start the inets service framework", []),
- case (catch inets:start()) of
- ok ->
- ?LOG("framework started", []),
- proxy_loop(Ref, CtrlNode);
- Error ->
- ?LOG("failed starting inets service framework: "
- "~n Error: ~p", [Error]),
- halt()
- end;
-
- {server_start, Config, From} ->
- ?LOG("start-server", []),
- maybe_start_crypto_and_ssl(Config),
- %% inets:enable_trace(max, "/tmp/inets-httpd-trace.log", httpd),
- %% inets:enable_trace(max, "/tmp/inets-httpd-trace.log", all),
- case (catch inets:start(httpd, Config)) of
- {ok, _} ->
- ?LOG("server started when"
- "~n which(inets): ~p"
- "~n RootDir: ~p"
- "~n System info: ~p", [code:which(inets),
- code:root_dir(),
- get_node_info()]),
- From ! {server_start_result, ok},
- proxy_loop(Ref, CtrlNode);
- Error ->
- ?INFO("server start failed"
- "~n Error: ~p", [Error]),
- From ! {server_start_result, Error},
- halt()
- end;
-
- {nodedown, CtrlNode} ->
- ?LOG("received nodedown for controller node - terminate", []),
- halt();
-
- {'DOWN', Ref, process, _, _} ->
- ?LOG("received DOWN message for controller - terminate", []),
- %% The controller has terminated, time to die
- halt()
-
- end.
-
-
-maybe_start_crypto_and_ssl(Config) ->
- case lists:keysearch(socket_type, 1, Config) of
- {value, {socket_type, SocketType}} when ((SocketType =:= ssl) orelse
- (SocketType =:= ossl) orelse
- (SocketType =:= essl)) ->
- ?LOG("maybe start crypto and ssl", []),
- (catch application:start(crypto)),
- ssl:start();
- _ ->
- ok
- end.
-
-
-get_node_info() ->
- [{cpu_topology, erlang:system_info(cpu_topology)},
- {heap_type, erlang:system_info(heap_type)},
- {nof_schedulers, erlang:system_info(schedulers)},
- {otp_release, erlang:system_info(otp_release)},
- {version, erlang:system_info(version)},
- {system_version, erlang:system_info(system_version)},
- {system_architecture, erlang:system_info(system_architecture)}].
-
diff --git a/lib/inets/examples/httpd_load_test/hdlt_slave.erl b/lib/inets/examples/httpd_load_test/hdlt_slave.erl
deleted file mode 100644
index 4daccef5da..0000000000
--- a/lib/inets/examples/httpd_load_test/hdlt_slave.erl
+++ /dev/null
@@ -1,293 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% SPDX-License-Identifier: Apache-2.0
-%%
-%% Copyright Ericsson AB 2010-2025. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
--module(hdlt_slave).
-
-
--export([start_link/4, start_link/5, start_link/6, stop/1]).
-
-%% Internal exports
--export([wait_for_slave/9, slave_start/1, wait_for_master_to_die/3]).
-
--include("hdlt_logger.hrl").
-
--define(SSH_PORT, 22).
--define(TIMEOUT, 60000).
--define(LOGGER, hdlt_logger).
-
-
-%% ***********************************************************************
-%% start_link/4,5 --
-%%
-%% The start/4,5 functions are used to start a slave Erlang node.
-%% The node on which the start/N functions are used is called the
-%% master in the description below.
-%%
-%% If hostname is the same for the master and the slave,
-%% the Erlang node will simply be spawned. The only requirement for
-%% this to work is that the 'erl' program can be found in PATH.
-%%
-%% If the master and slave are on different hosts, start/N uses
-%% the 'ssh' program to spawn an Erlang node on the other host.
-%% Alternative, if the master was started as
-%% 'erl -sname xxx -rsh my_rsh...', then 'my_rsh' will be used instead
-%% of 'ssh' (this is useful for systems still using rsh or remsh).
-%%
-%% For this to work, the following conditions must be fulfilled:
-%%
-%% 1. There must be an ssh program on computer; if not an error
-%% is returned.
-%%
-%% 2. The hosts must be configured to allow 'ssh' access without
-%% prompts for password.
-%%
-%% The slave node will have its filer and user server redirected
-%% to the master. When the master node dies, the slave node will
-%% terminate. For the start_link functions, the slave node will
-%% terminate also if the process which called start_link terminates.
-%%
-%% Returns: {ok, Name@Host} |
-%% {error, timeout} |
-%% {error, no_rsh} |
-%% {error, {already_running, Name@Host}}
-
-start_link(Host, Name, ErlPath, Paths) ->
- start_link(Host, Name, ErlPath, Paths, [], silence).
-
-start_link(Host, Name, ErlPath, Paths, DebugLevel) when is_atom(DebugLevel) ->
- start_link(Host, Name, ErlPath, Paths, [], DebugLevel);
-start_link(Host, Name, ErlPath, Paths, Args) when is_list(Args) ->
- start_link(Host, Name, ErlPath, Paths, Args, silence).
-
-start_link(Host, Name, ErlPath, Paths, Args, DebugLevel) ->
- Node = list_to_atom(lists:concat([Name, "@", Host])),
- case net_adm:ping(Node) of
- pang ->
- start_it(Host, Name, Node, ErlPath, Paths, Args, DebugLevel);
- pong ->
- {error, {already_running, Node}}
- end.
-
-%% Stops a running node.
-
-stop(Node) ->
- rpc:call(Node, erlang, halt, []),
- ok.
-
-
-%% Starts a new slave node.
-
-start_it(Host, Name, Node, ErlPath, Paths, Args, DebugLevel) ->
- Prog = filename:join([ErlPath, "erl"]),
- spawn(?MODULE, wait_for_slave, [self(), Host, Name, Node, Paths, Args, self(), Prog, DebugLevel]),
- receive
- {result, Result} -> Result
- end.
-
-%% Waits for the slave to start.
-
-wait_for_slave(Parent, Host, Name, Node, Paths, Args,
- LinkTo, Prog, DebugLevel) ->
- ?SET_NAME("HDLT SLAVE STARTER"),
- ?SET_LEVEL(DebugLevel),
- ?DEBUG("begin", []),
- Waiter = register_unique_name(0),
- case (catch mk_cmd(Host, Name, Paths, Args, Waiter, Prog)) of
- {ok, Cmd} ->
- ?DEBUG("command generated: ~n~s", [Cmd]),
- case (catch ssh_slave_start(Host, Cmd)) of
- {ok, Conn, _Chan} ->
- ?DEBUG("ssh channel created", []),
- receive
- {SlavePid, slave_started} ->
- ?DEBUG("slave started: ~p", [SlavePid]),
- unregister(Waiter),
- slave_started(Parent, LinkTo, SlavePid, Conn,
- DebugLevel)
- after 32000 ->
- ?INFO("slave node failed to report in on time",
- []),
- %% If it seems that the node was partially started,
- %% try to kill it.
- case net_adm:ping(Node) of
- pong ->
- spawn(Node, erlang, halt, []),
- ok;
- _ ->
- ok
- end,
- Parent ! {result, {error, timeout}}
- end;
- {error, Reason} = Error ->
- ?INFO("FAILED starting node: "
- "~n ~p"
- "~n ~p", [Reason, Cmd]),
- Parent ! {result, Error}
- end;
- Other ->
- ?INFO("FAILED creating node command string: "
- "~n ~p", [Other]),
- Parent ! {result, Other}
- end.
-
-
-ssh_slave_start(Host, ErlCmd) ->
- ?DEBUG("ssh_slave_start -> try connect to ~p", [Host]),
- Connection =
- case (catch ssh:connect(Host, ?SSH_PORT,
- [{silently_accept_hosts, true}])) of
- {ok, Conn} ->
- ?DEBUG("ssh_exec_erl -> connected: ~p", [Conn]),
- Conn;
- Error1 ->
- ?LOG("failed connecting to ~p: ~p", [Host, Error1]),
- throw({error, {ssh_connect_failed, Error1}})
- end,
-
- ?DEBUG("ssh_exec_erl -> connected - now create channel", []),
- Channel =
- case (catch ssh_connection:session_channel(Connection, ?TIMEOUT)) of
- {ok, Chan} ->
- ?DEBUG("ssh_exec_erl -> channel ~p created", [Chan]),
- Chan;
- Error2 ->
- ?LOG("failed creating channel: ~p", [Error2]),
- throw({error, {ssh_channel_create_failed, Error2}})
- end,
-
- ?DEBUG("ssh_exec_erl -> channel created - now exec command: "
- "~n ~p", [ErlCmd]),
- case (catch ssh_connection:exec(Connection, Channel, ErlCmd, infinity)) of
- success ->
- ?DEBUG("ssh_exec_erl -> command exec'ed - clean ssh msg", []),
- clean_ssh_msg(),
- ?DEBUG("ssh_exec_erl -> done", []),
- {ok, Connection, Channel};
- Error3 ->
- ?LOG("failed exec command: ~p", [Error3]),
- throw({error, {ssh_exec_failed, Error3}})
- end.
-
-clean_ssh_msg() ->
- receive
- {ssh_cm, _X, _Y} ->
- clean_ssh_msg()
- after 1000 ->
- ok
- end.
-
-
-slave_started(ReplyTo, Master, Slave, Conn, Level)
- when is_pid(Master) andalso is_pid(Slave) ->
- process_flag(trap_exit, true),
- SName = lists:flatten(
- io_lib:format("HDLT SLAVE CTRL[~p,~p]",
- [self(), node(Slave)])),
- ?SET_NAME(SName),
- ?SET_LEVEL(Level),
- ?LOG("initiating", []),
- MasterRef = erlang:monitor(process, Master),
- SlaveRef = erlang:monitor(process, Slave),
- ReplyTo ! {result, {ok, node(Slave)}},
- slave_running(Master, MasterRef, Slave, SlaveRef, Conn).
-
-
-%% The slave node will be killed if the master process terminates,
-%% The master process will not be killed if the slave node terminates.
-
-slave_running(Master, MasterRef, Slave, SlaveRef, Conn) ->
- ?DEBUG("await message", []),
- receive
- {'DOWN', MasterRef, process, _Object, _Info} ->
- ?LOG("received DOWN from master", []),
- erlang:demonitor(SlaveRef, [flush]),
- Slave ! {nodedown, node()},
- ssh:close(Conn);
-
- {'DOWN', SlaveRef, process, Object, _Info} ->
- ?LOG("received DOWN from slave (~p)", [Object]),
- erlang:demonitor(MasterRef, [flush]),
- ssh:close(Conn);
-
- Other ->
- ?DEBUG("received unknown: ~n~p", [Other]),
- slave_running(Master, MasterRef, Slave, SlaveRef, Conn)
-
- end.
-
-register_unique_name(Number) ->
- Name = list_to_atom(lists:concat([?MODULE, "_waiter_", Number])),
- case catch register(Name, self()) of
- true ->
- Name;
- {'EXIT', {badarg, _}} ->
- register_unique_name(Number+1)
- end.
-
-
-%% Makes up the command to start the nodes.
-%% If the node should run on the local host, there is
-%% no need to use ssh.
-
-mk_cmd(Host, Name, Paths, Args, Waiter, Prog) ->
- PaPaths = [[" -pa ", Path] || Path <- Paths],
- {ok, lists:flatten(
- lists:concat([Prog,
- " -detached -nopinput ",
- Args, " ",
- " -sname ", Name, "@", Host,
- " -s ", ?MODULE, " slave_start ", node(),
- " ", Waiter,
- " ", PaPaths]))}.
-
-
-%% This function will be invoked on the slave, using the -s option of erl.
-%% It will wait for the master node to terminate.
-
-slave_start([Master, Waiter]) ->
- spawn(?MODULE, wait_for_master_to_die, [Master, Waiter, silence]);
-slave_start([Master, Waiter, Level]) ->
- spawn(?MODULE, wait_for_master_to_die, [Master, Waiter, Level]).
-
-
-wait_for_master_to_die(Master, Waiter, Level) ->
- process_flag(trap_exit, true),
- SName = lists:flatten(
- io_lib:format("HDLT-SLAVE MASTER MONITOR[~p,~p,~p]",
- [self(), node(), Master])),
- ?SET_NAME(SName),
- ?SET_LEVEL(Level),
- erlang:monitor_node(Master, true),
- {Waiter, Master} ! {self(), slave_started},
- wloop(Master).
-
-wloop(Master) ->
- ?DEBUG("await message", []),
- receive
- {nodedown, Master} ->
- ?INFO("received master nodedown", []),
- halt();
- _Other ->
- wloop(Master)
- end.
-
-
-
diff --git a/lib/inets/examples/httpd_load_test/hdlt_ssl_client_cert.pem b/lib/inets/examples/httpd_load_test/hdlt_ssl_client_cert.pem
deleted file mode 120000
index 41644a1098..0000000000
--- a/lib/inets/examples/httpd_load_test/hdlt_ssl_client_cert.pem
+++ /dev/null
@@ -1 +0,0 @@
-../../test/httpc_SUITE_data/ssl_client_cert.pem
\ No newline at end of file
diff --git a/lib/inets/examples/httpd_load_test/hdlt_ssl_server_cert.pem b/lib/inets/examples/httpd_load_test/hdlt_ssl_server_cert.pem
deleted file mode 120000
index 41644a1098..0000000000
--- a/lib/inets/examples/httpd_load_test/hdlt_ssl_server_cert.pem
+++ /dev/null
@@ -1 +0,0 @@
-../../test/httpc_SUITE_data/ssl_client_cert.pem
\ No newline at end of file
diff --git a/lib/inets/examples/httpd_load_test/modules.mk b/lib/inets/examples/httpd_load_test/modules.mk
deleted file mode 100644
index 3613467751..0000000000
--- a/lib/inets/examples/httpd_load_test/modules.mk
+++ /dev/null
@@ -1,47 +0,0 @@
-#-*-makefile-*- ; force emacs to enter makefile-mode
-
-# %CopyrightBegin%
-#
-# SPDX-License-Identifier: Apache-2.0
-#
-# Copyright Ericsson AB 2010-2025. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-
-SCRIPT_SKELETONS = \
- hdlt.sh.skel
-
-CONF_SKELETONS = \
- hdlt.config.skel
-
-CERT_FILES = \
- hdlt_ssl_client_cert.pem \
- hdlt_ssl_server_cert.pem
-
-README = HDLT_README
-
-MODULES = \
- hdlt \
- hdlt_ctrl \
- hdlt_client \
- hdlt_logger \
- hdlt_random_html \
- hdlt_server \
- hdlt_slave
-
-INTERNAL_HRL_FILES = \
- hdlt_logger.hrl
-
-
diff --git a/lib/inets/examples/subdirs.mk b/lib/inets/examples/subdirs.mk
index 10a331fc26..28f388e354 100644
--- a/lib/inets/examples/subdirs.mk
+++ b/lib/inets/examples/subdirs.mk
@@ -1,3 +1,22 @@
#-*-makefile-*- ; force emacs to enter makefile-mode
-
-SUB_DIRECTORIES = server_root httpd_load_test
\ No newline at end of file
+# %CopyrightBegin%
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# Copyright Ericsson AB 2009-2025. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# %CopyrightEnd%
+#
+SUB_DIRECTORIES = server_root
diff --git a/lib/inets/test/Makefile b/lib/inets/test/Makefile
index 256408282d..3050c006b0 100644
--- a/lib/inets/test/Makefile
+++ b/lib/inets/test/Makefile
@@ -66,9 +66,9 @@ INETS_FLAGS = -Dinets_data_dir='"$(INETS_DATA_DIR)"' \
-Dinets_priv_dir='"$(INETS_PRIV_DIR)"'
-###
+###
### test suite debug flags
-###
+###
ifeq ($(INETS_DEBUG),)
INETS_DEBUG = d
endif
@@ -82,9 +82,9 @@ ifeq ($(INETS_DEBUG),d)
endif
-###
+###
### HTTPD verbosity flags
-###
+###
ifneq ($(MANV),)
INETS_FLAGS += -Dhttpd_manager_verbosity=$(MANV)
@@ -122,13 +122,13 @@ INETS_ROOT = ../../inets
MODULES = \
inets_test_lib \
- make_certs \
+ httpd_bench_certs \
http_format_SUITE \
httpc_SUITE \
httpc_cookie_SUITE \
httpc_proxy_SUITE \
httpd_SUITE \
- httpd_bench_SUITE \
+ httpd_bench_SUITE \
http_test_lib \
httpd_basic_SUITE \
httpd_serve_SUITE \
@@ -152,7 +152,7 @@ HRL_FILES = inets_test_lib.hrl \
ERL_FILES = $(MODULES:%=%.erl)
-SOURCE = $(ERL_FILES) $(HRL_FILES)
+SOURCE = $(ERL_FILES) $(HRL_FILES)
TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR))
@@ -196,7 +196,7 @@ RELTESTSYSBINDIR = $(RELTESTSYSALLDATADIR)/bin
# ----------------------------------------------------
# FLAGS
-# The path to the test_server ebin dir is needed when
+# The path to the test_server ebin dir is needed when
# running the target "targets".
# ----------------------------------------------------
ERL_COMPILE_FLAGS += \
@@ -213,7 +213,7 @@ ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
# 1) INETS_PRIV_DIR must be created
# ----------------------------------------------------
-tests $(TYPES): $(BUILDTARGET)
+tests $(TYPES): $(BUILDTARGET)
targets: $(TARGET_FILES)
@@ -221,7 +221,7 @@ targets: $(TARGET_FILES)
emakebuild: $(EMAKEFILE)
-$(EMAKEFILE):
+$(EMAKEFILE):
$(MAKE_EMAKE) $(ERL_COMPILE_FLAGS) -o$(EBIN) '*_SUITE_make' | grep -v Warning > $(EMAKEFILE)
$(MAKE_EMAKE) $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) | grep -v Warning >> $(EMAKEFILE)
@@ -235,7 +235,7 @@ docs:
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
@@ -268,7 +268,7 @@ release_tests_spec: opt
$(INSTALL_DIR) $(RELTESTSYSALLDATADIR)
$(INSTALL_DIR) $(RELTESTSYSBINDIR)
chmod -R +x $(RELTESTSYSBINDIR)
- $(INSTALL_DIR) $(RELTESTSYSALLDATADIR)/win32/lib
+ $(INSTALL_DIR) $(RELTESTSYSALLDATADIR)/win32/lib
release_docs_spec:
diff --git a/lib/inets/test/httpd_bench_SUITE.erl b/lib/inets/test/httpd_bench_SUITE.erl
index 6fba8b919a..d1019da363 100644
--- a/lib/inets/test/httpd_bench_SUITE.erl
+++ b/lib/inets/test/httpd_bench_SUITE.erl
@@ -23,13 +23,18 @@
%%
-module(httpd_bench_SUITE).
--compile(export_all).
-include_lib("common_test/include/ct.hrl").
-include_lib("common_test/include/ct_event.hrl").
--include_lib("public_key/include/public_key.hrl").
-include_lib("kernel/include/file.hrl").
+-export([suite/0, all/0, groups/0, init_per_suite/1, end_per_suite/1, init_per_group/2, end_per_group/2,
+ init_per_testcase/2, end_per_testcase/2, wget_small/1, erl_dummy_small/1, httpc_small/1, wget_big/1,
+ erl_dummy_big/1, httpc_big/1]).
+-export([httpc_client/1, httpc_client/2, httpd_lib_client/1, httpd_lib_client/2,
+ wget_client/1, wget_client/2, wget/4]).
+-export([handle_http_msg/3]).
+
-define(remote_host, "NETMARKS_REMOTE_HOST").
-define(LF, [10]).
-define(CR, [13]).
@@ -38,11 +43,10 @@
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
-suite() ->
- [{timetrap, {minutes, 1}},
- {ct_hooks,[{ts_install_cth,[{nodenames,2}]}]}].
+suite() ->
+ [{timetrap, {minutes, 1}}].
-all() ->
+all() ->
[
{group, http_dummy},
{group, http_inets},
@@ -58,12 +62,12 @@ all() ->
{group, https_nginx_keep_alive}
].
-groups() ->
+groups() ->
[
{http_dummy, [], client_tests()},
{http_inets, [], client_tests()},
{http_nginx, [], client_tests()},
- {https_dummy, [], client_tests()},
+ {https_dummy, [], client_tests()},
{https_inets, [], client_tests()},
{https_nginx, [], client_tests()},
{http_dummy_keep_alive, [], client_tests()},
@@ -74,54 +78,58 @@ groups() ->
{https_nginx_keep_alive, [], client_tests()}
].
-
+
client_tests() ->
[wget_small,
erl_dummy_small,
httpc_small,
wget_big,
- erl_dummy_big,
+ erl_dummy_big,
httpc_big
].
-init_per_suite(Config) ->
- try
- {Node, Host} = setup(Config, node()),
- init_ssl(Config),
- [{iter, 10}, {server_node, Node}, {server_host, Host} | Config]
+init_per_suite(Config) ->
+ try
+ Setup = setup(Config, node()),
+ init_ssl(Config),
+ Setup ++ [{iter, 10} | Config]
catch E:R:ST ->
- ct:log("~p:~p:~p",[E,R,ST]),
- {skipped, "Benchmark machines only"}
+ ct:log("~p:~p:~p",[E,R,ST]),
+ {skipped, "Benchmark machines only"}
end.
-end_per_suite(_Config) ->
- [application:stop(App) || App <- [asn1, crypto, public_key, ssl, inets]].
+end_per_suite(Config) ->
+ [application:stop(App) || App <- [asn1, crypto, public_key, ssl, inets]],
+ PeerPid = proplists:get_value(server_pid, Config),
+ peer:stop(PeerPid).
-init_per_group(Group, Config) when Group == http_dummy_keep_alive;
+%% Init keepalive servers group
+init_per_group(Group, Config) when Group == http_dummy_keep_alive;
Group == https_dummy_keep_alive;
- Group == http_inets_keep_alive;
+ Group == http_inets_keep_alive;
Group == https_inets_keep_alive;
Group == http_nginx_keep_alive;
Group == https_nginx_keep_alive ->
Version = http_version(Group),
start_web_server(Group,
- [{keep_alive, true},
+ [{keep_alive, true},
{reuse_sessions, false},
{http_version, Version},
{http_opts,[{version, Version}]},
{http_headers, [{"connection", "keep-alive"}]},
- {httpc_opts, [{keep_alive_timeout, 1500},
+ {httpc_opts, [{keep_alive_timeout, 1500},
{max_keep_alive_length, ?config(iter, Config)}]}
| Config]);
-init_per_group(Group, Config) when Group == http_dummy;
+%% Init non-keepalive servers group
+init_per_group(Group, Config) when Group == http_dummy;
Group == https_dummy;
- Group == http_inets;
+ Group == http_inets;
Group == https_inets;
Group == http_nginx;
Group == https_nginx ->
Version = http_version(Group),
- start_web_server(Group,
- [{keep_alive, false},
+ start_web_server(Group,
+ [{keep_alive, false},
{reuse_sessions, false},
{http_version, Version},
{http_headers, [{"connection", "close"}]},
@@ -138,60 +146,61 @@ end_per_group(Group, Config) ->
init_per_testcase(TestCase, Config) when TestCase == httpc_small;
TestCase == httpc_big
- ->
+ ->
Opts = ?config(httpc_opts, Config),
inets:start(httpc, [{profile, TestCase}, {socket_opts, [{nodelay, true}]}]),
httpc:set_options(Opts, TestCase),
[{profile, TestCase} | proplists:delete(profile, Config)];
-init_per_testcase(_, Config) ->
+init_per_testcase(_, Config) ->
Config.
end_per_testcase(TestCase, _Config) when TestCase == httpc_small;
- TestCase == httpc_big ->
+ TestCase == httpc_big ->
ok = inets:stop(httpc, TestCase);
-end_per_testcase(_TestCase, Config) ->
+end_per_testcase(_TestCase, Config) ->
Config.
%%--------------------------------------------------------------------
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
-erl_dummy_small(Config) when is_list(Config) ->
+erl_dummy_small(Config) when is_list(Config) ->
{ok, Result} = run_test(httpd_lib_client, "1k_file", Config),
- notify(Result, Config, "erl_1k_file").
+ notify(Result, Config, "erl_1k_file").
-erl_dummy_big(Config) when is_list(Config) ->
+erl_dummy_big(Config) when is_list(Config) ->
{ok, Result} = run_test(httpd_lib_client, "1M_file", Config),
- notify(Result, Config, "erl_1M_file").
+ notify(Result, Config, "erl_1M_file").
-wget_small(Config) when is_list(Config) ->
+wget_small(Config) when is_list(Config) ->
{ok, Result} = run_test(wget_client, "1k_file", Config),
- notify(Result, Config, "wget_1k_file").
+ notify(Result, Config, "wget_1k_file").
-wget_big(Config) when is_list(Config) ->
+wget_big(Config) when is_list(Config) ->
{ok, Result} = run_test(wget_client, "1M_file", Config),
- notify(Result, Config, "wget_1M_file").
+ notify(Result, Config, "wget_1M_file").
-httpc_small(Config) when is_list(Config) ->
+httpc_small(Config) when is_list(Config) ->
{ok, Result} = run_test(httpc_client, "1k_file", Config),
- notify(Result, Config, "httpc_1k_file").
+ notify(Result, Config, "httpc_1k_file").
-httpc_big(Config) when is_list(Config) ->
+httpc_big(Config) when is_list(Config) ->
{ok, Result} = run_test(httpc_client, "1M_file", Config),
- notify(Result, Config, "httpc_1M_file").
+ notify(Result, Config, "httpc_1M_file").
%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
+%%
%%--------------------------------------------------------------------
%% Report benchmark results ------------------------------------------------
%%--------------------------------------------------------------------
notify({TestPerSec, _MBps}, Config, Suffix) ->
- Name = lists:concat([?config(protocol,Config), " ",
- server_name(Config, [dummy_pid, httpd_pid, nginx_port]),
+ Name = lists:concat([?config(protocol,Config), " ",
+ server_name(Config, [dummy_pid, httpd_pid, nginx_port]),
"", Suffix]),
- ct:comment("~p tps", [TestPerSec]),
+ ct:comment("~p tests/s", [TestPerSec]),
ct_event:notify(#event{name = benchmark_data,
data=[{value, TestPerSec},
{suite, ?MODULE},
@@ -209,9 +218,9 @@ server_name(Config, [Server | Rest]) ->
server_name(Server)
end.
-server_name(httpd_pid) ->
- "inets";
-server_name(nginx_port) ->
+server_name(httpd_pid) ->
+ "inets";
+server_name(nginx_port) ->
"nginx";
server_name(dummy_pid) ->
"erlang".
@@ -220,34 +229,33 @@ setup(_Config, nonode@nohost) ->
exit(dist_not_enabled);
setup(_Config, _LocalNode) ->
Host = case os:getenv(?remote_host) of
- false ->
- {ok, This} = inet:gethostname(),
- This;
- RemHost ->
- RemHost
- end,
- Node = list_to_atom("inets_perf_server@" ++ Host),
- SlaveArgs = case init:get_argument(pa) of
- {ok, PaPaths} ->
- lists:append([" -pa " ++ P || [P] <- PaPaths]);
- _ -> []
- end,
- Prog =
- case os:find_executable("erl") of
- false -> "erl";
- P -> P
- end,
- case net_adm:ping(Node) of
- pong -> ok;
- pang ->
- {ok, Node} = slave:start(Host, inets_perf_server, SlaveArgs, no_link, Prog)
- end,
+ false -> net_adm:localhost();
+ RemHost -> RemHost
+ end,
+ PeerArgs = case init:get_argument(pa) of
+ {ok, PaPaths} -> ["-pa"] ++ lists:concat(PaPaths);
+ _ -> []
+ end,
+ Prog = case os:find_executable("erl") of
+ false -> "erl";
+ P -> P
+ end,
+ PeerOpts = #{
+ name => inets_perf_server,
+ args => PeerArgs,
+ peer_down => crash,
+ exec => Prog
+ },
+ ct:pal("about to start peer...", []),
+ {ok, PeerPid, Node} = peer:start(PeerOpts),
+ ct:pal("started peer ~0p", [Node]),
Path = code:get_path(),
true = rpc:call(Node, code, set_path, [Path]),
[ensure_started(Node, App) || App <- [asn1, crypto, public_key, ssl, inets]],
[ensure_started(node(), App) || App <- [asn1, crypto, public_key, ssl, inets]],
(Node =:= node()) andalso restrict_schedulers(client),
- {Node, Host}.
+ %% Return also the pid for peer control
+ [{server_node, Node}, {server_host, Host}, {server_pid, PeerPid}].
ensure_started(Node, App) ->
ok = rpc:call(Node, application, ensure_started, [App]).
@@ -265,42 +273,31 @@ restrict_schedulers(Type) ->
%%--------------------------------------------------------------------
init_ssl(Config) ->
- DDir = ?config(data_dir, Config),
+%% DDir = ?config(data_dir, Config),
PDir = ?config(priv_dir, Config),
- {ok, _} = make_certs:all(DDir,
- PDir).
+%% {ok, _} = make_certs:all(DDir, PDir).
+ httpd_bench_certs:make_cert_files(PDir).
+
cert_opts(Config) ->
- ClientCaCertFile = filename:join([?config(priv_dir, Config),
- "client", "cacerts.pem"]),
- ClientCertFile = filename:join([?config(priv_dir, Config),
- "client", "cert.pem"]),
- ServerCaCertFile = filename:join([?config(priv_dir, Config),
- "server", "cacerts.pem"]),
- ServerCertFile = filename:join([?config(priv_dir, Config),
- "server", "cert.pem"]),
- ServerKeyFile = filename:join([?config(priv_dir, Config),
- "server", "key.pem"]),
- ClientKeyFile = filename:join([?config(priv_dir, Config),
- "client", "key.pem"]),
+ PrivDir = ?config(priv_dir, Config),
+ ServerCaCertFile = filename:join([PrivDir, "server-cacerts.pem"]),
+ ServerCertFile = filename:join([PrivDir, "server-cert.pem"]),
+ ServerKeyFile = filename:join([PrivDir, "server-key.pem"]),
[{server_verification_opts, [{cacertfile, ServerCaCertFile},
- {ciphers, ["ECDHE-RSA-AES256-GCM-SHA384",
- "TLS_AES_256_GCM_SHA384"]},
- {certfile, ServerCertFile}, {keyfile, ServerKeyFile}]},
- {client_verification_opts, [
- %%{verify, verify_peer},
- {cacertfile, ClientCaCertFile},
- {certfile, ClientCertFile},
- {keyfile, ClientKeyFile}]}].
+ {ciphers, ["ECDHE-RSA-AES256-GCM-SHA384", "TLS_AES_256_GCM_SHA384"]},
+ {certfile, ServerCertFile},
+ {keyfile, ServerKeyFile}]},
+ {client_verification_opts, [{cacertfile, ServerCaCertFile}]}].
%%--------------------------------------------------------------------
%% Run clients ------------------------------------------------
%%--------------------------------------------------------------------
-run_test(Client, File, Config) ->
+run_test(Client, File, Config) ->
Parent = self(),
Pid = spawn(fun() ->
receive
- go ->
+ go ->
Parent ! {self(),
do_runs(Client, [{file, File} | Config])}
end
@@ -316,13 +313,12 @@ do_runs(Client, Config) ->
N = ?config(iter, Config),
DataDir = ?config(data_dir, Config),
File = ?config(file, Config),
- Name = filename:join(DataDir, File),
+ Name = filename:join(DataDir, File),
Args = ?MODULE:Client(Config),
?MODULE:Client({init, Args}),
- Run =
- fun() ->
- ok = ?MODULE:Client(Args, N)
- end,
+ Run = fun() ->
+ ok = ?MODULE:Client(Args, N)
+ end,
{ok, Info} = file:read_file_info(Name, []),
Length = Info#file_info.size,
{TimeInMicro, _} = timer:tc(Run),
@@ -330,12 +326,15 @@ do_runs(Client, Config) ->
BytesPerSecond = (1000000 * N * Length) div TimeInMicro,
{{tps, ReqPerSecond}, {mbps, BytesPerSecond}}.
-
+%% Client handler for httpc-based test cases
+%% httpc_client/1 is called once with the config, to create args which will be then passed
+%% again into httpc_client/1 as {init, Args}.
httpc_client({init, [_, Profile, URL, Headers, HTTPOpts]}) ->
- %% Make sure pipelining feature will kick in when appropriate.
- {ok, {{_ ,200, "OK"}, _,_}} = httpc:request(get,{URL, Headers}, HTTPOpts,
- [{body_format, binary},
- {socket_opts, [{nodelay, true}]}], Profile),
+ %% Make sure pipelining feature will kick in when appropriate.
+ {ok, {{_ ,200, "OK"}, _,_}} = httpc:request(
+ get,{URL, Headers}, HTTPOpts,
+ [{body_format, binary}, {socket_opts, [{nodelay, true}]}],
+ Profile),
ct:sleep(1000);
httpc_client(Config) ->
File = ?config(file, Config),
@@ -343,18 +342,36 @@ httpc_client(Config) ->
Profile = ?config(profile, Config),
URL = (?config(urlfun,Config))(File),
Headers = ?config(http_headers, Config),
- HTTPOpts = ?config(http_opts, Config),
+ HTTPOpts = ?config(http_opts, Config)
+ ++ case Protocol of
+ "http" -> [];
+ "https" -> % httpc would like to know more about certificates used in the test
+ AllCertOpts = proplists:get_value(client_verification_opts, cert_opts(Config)),
+ SSLOpts = [
+ {verify, verify_peer}, % this is the default
+ {cacertfile, proplists:get_value(cacertfile, AllCertOpts)}
+ ],
+ [{ssl, SSLOpts}]
+ end,
[Protocol, Profile, URL, Headers, HTTPOpts].
+
+%% This will receive arguments (Args, N) where N is iterations count,
+%% with Args produced by httpc_client/1 above.
httpc_client(_,0) ->
ok;
httpc_client([Protocol, Profile, URL, Headers, HTTPOpts], N) ->
- {ok, {{_ ,200,"OK"}, _,_}} = httpc:request(get,{URL, Headers}, HTTPOpts, [{body_format, binary},
- {socket_opts, [{nodelay, true}]}], Profile),
+ {ok, {{_ ,200,"OK"}, _,_}} = httpc:request(
+ get,{URL, Headers}, HTTPOpts,
+ [{body_format, binary}, {socket_opts, [{nodelay, true}]}],
+ Profile),
httpc_client([Protocol, Profile, URL, Headers, HTTPOpts], N-1).
+%% Client handler based on httpd_test_lib
+%% httpd_lib_client/1 is called once with the config, to create args which will be then passed
+%% again into httpd_lib_client/1 as {init, Args}.
httpd_lib_client({init, [_, Type, Version, Request, Host, Port, Opts]}) ->
- ok = httpd_test_lib:verify_request(Type, Host,
- Port,
+ ok = httpd_test_lib:verify_request(Type, Host,
+ Port,
Opts, node(),
Request,
[{statuscode, 200},
@@ -366,15 +383,15 @@ httpd_lib_client(Config) ->
Host = ?config(server_host, Config),
Port = ?config(port, Config),
ReuseSession = ?config(reuse_sessions, Config),
- {Type, Opts} =
+ {Type, Opts} =
case ?config(protocol, Config) of
"http" ->
{ip_comm, [{active, true}, {mode, binary},{nodelay, true}]};
- "https" ->
+ "https" ->
SSLOpts = proplists:get_value(client_verification_opts, cert_opts(Config)),
- {ssl, [{active, true}, {mode, binary}, {nodelay, true},
+ {ssl, [{active, true}, {mode, binary}, {nodelay, true},
{reuse_sessions, ReuseSession} | SSLOpts]}
-
+
end,
Version = ?config(http_version, Config),
Request = case KeepAlive of
@@ -383,29 +400,34 @@ httpd_lib_client(Config) ->
false ->
http_request("GET /" ++ File ++ " ", Version, Host)
end,
-
+
Args = [KeepAlive, Type, Version, Request, Host, Port, Opts],
httpd_lib_client(Args, 1),
Args.
+%% This will receive arguments (Args, N) where N is iterations count,
+%% with Args produced by httpd_lib_client/1 above.
httpd_lib_client(_, 0) ->
ok;
httpd_lib_client([true, Type, Version, Request, Host, Port, Opts], N) ->
- ok = httpd_test_lib:verify_request_N(Type, Host,
- Port,
+ ok = httpd_test_lib:verify_request_N(Type, Host,
+ Port,
Opts, node(),
Request,
[{statuscode, 200},
{version, Version}], infinity, N);
httpd_lib_client([false, Type, Version, Request, Host, Port, Opts] = List, N) ->
- ok = httpd_test_lib:verify_request(Type, Host,
- Port,
+ ok = httpd_test_lib:verify_request(Type, Host,
+ Port,
Opts, node(),
Request,
[{statuscode, 200},
{version, Version}], infinity),
httpd_lib_client(List, N-1).
+%% Client handler for wget-based test cases
+%% wget_client/1 is called once with the config, to create args which will be then passed
+%% again into wget_client/1 as {init, Args}.
wget_client({init,_}) ->
ok;
wget_client(Config) ->
@@ -417,18 +439,19 @@ wget_client(Config) ->
Iter = ?config(iter, Config),
FileName = filename:join(PrivDir, "wget_req"),
ProtocolOpts = case Protocol of
- "http" ->
- [];
- "https" ->
- proplists:get_value(client_verification_opts, cert_opts(Config))
- end,
+ "http" -> [];
+ "https" -> proplists:get_value(client_verification_opts, cert_opts(Config))
+ end,
wget_req_file(FileName,URL,Iter),
[KeepAlive, FileName, URL, Protocol, ProtocolOpts, Iter].
-wget_client([KeepAlive, WgetFile, _URL, Protocol, ProtocolOpts, _], _) ->
+
+%% This will receive arguments (Args, N) where N is iterations count,
+%% with Args produced by wget_client/1 above.
+wget_client([KeepAlive, WgetFile, _URL, Protocol, ProtocolOpts, _], _Iter) ->
process_flag(trap_exit, true),
Cmd = wget_N(KeepAlive, WgetFile, Protocol, ProtocolOpts),
%%ct:log("Wget cmd: ~p", [Cmd]),
- Port = open_port({spawn, Cmd}, [stderr_to_stdout]),
+ Port = open_port({spawn, Cmd}, [stderr_to_stdout]),
wait_for_wget(Port).
@@ -446,13 +469,14 @@ start_web_server(Group, Config) when Group == https_dummy;
start_web_server(Group, Config) when Group == http_inets;
Group == http_inets_keep_alive ->
start_inets("http", [], Config);
-
+
start_web_server(Group, Config) when Group == https_inets;
Group == https_inets_keep_alive ->
Opts = proplists:get_value(server_verification_opts, cert_opts(Config)),
ReuseSessions = ?config(reuse_sessions, Config),
- SSLConfHttpd = [{socket_type, {ssl,
- [{nodelay, true}, {reuse_sessions, ReuseSessions} | Opts]}}],
+ SSLConfHttpd = [{socket_type,
+ {ssl, [{nodelay, true}, {reuse_sessions, ReuseSessions} | Opts]}
+ }],
start_inets("https", SSLConfHttpd, Config);
start_web_server(Group, Config) when Group == http_nginx;
@@ -470,33 +494,33 @@ start_web_server(Group, Config) when Group == https_nginx;
false ->
{skip, "nginx not found"};
_ ->
- start_nginx("https", cert_opts(Config) ++ Config)
+ start_nginx("https", cert_opts(Config) ++ Config)
end.
-
+
start_inets(Protocol, ConfHttpd, Config) ->
PrivDir = ?config(priv_dir, Config),
DataDir = ?config(data_dir, Config),
Node = ?config(server_node, Config),
- Host = ?config(server_host, Config),
- HTTPVersion = ?config(http_version, Config),
+ Host = ?config(server_host, Config),
+ HTTPVersion = ?config(http_version, Config),
Conf = [httpd, [{port,0},
{http_version, HTTPVersion},
{ipfamily, inet},
- {server_name, "inets_test"},
- {server_root, PrivDir},
+ {server_name, net_adm:localhost()}, % also the default
+ {server_root, PrivDir},
{document_root, DataDir},
{keep_alive, ?config(keep_alive, Config)},
{keep_alive_timeout, 360}
| ConfHttpd]],
{ok, Pid} = rpc:call(Node, inets, start, Conf),
Port = proplists:get_value(port, rpc:call(Node, httpd, info, [Pid])),
- F = fun(File) ->
- lists:concat([Protocol,"://",Host,":",Port,"/",File])
+ F = fun(File) ->
+ lists:concat([Protocol,"://",Host,":",Port,"/",File])
end,
[{httpd_pid,Pid},{urlfun,F},{protocol,Protocol},{port,Port} | Config].
start_dummy("http"= Protocol, Config) ->
- HTTPVersion = ?config(http_version, Config),
+ HTTPVersion = ?config(http_version, Config),
Node = ?config(server_node, Config),
%%DataDir= ?config(data_dir, Config),
Host = ?config(server_host, Config),
@@ -509,13 +533,13 @@ start_dummy("http"= Protocol, Config) ->
{keep_alive, ?config(keep_alive, Config)}
],
{Pid, Port} = rpc:call(Node, http_test_lib, dummy_server, [ip_comm, inet, [{content_cb, ?MODULE}, {conf, Conf}]]),
- F = fun(File) ->
- lists:concat([Protocol,"://",Host,":",Port,"/",File])
+ F = fun(File) ->
+ lists:concat([Protocol,"://",Host,":",Port,"/",File])
end,
[{dummy_pid,Pid},{urlfun,F},{protocol, Protocol},{port,Port} | Config];
start_dummy("https" = Protocol, Config) ->
- HTTPVersion = ?config(http_version, Config),
+ HTTPVersion = ?config(http_version, Config),
Node = ?config(server_node, Config),
%% DataDir= ?config(data_dir, Config),
Host = ?config(server_host, Config),
@@ -530,55 +554,55 @@ start_dummy("https" = Protocol, Config) ->
],
{Pid, Port} = rpc:call(Node, http_test_lib, dummy_server,
[ssl, inet, [{ssl, Opts}, {content_cb, ?MODULE}, {conf, Conf}]]),
- F = fun(File) ->
- lists:concat([Protocol,"://",Host,":",Port,"/",File])
+ F = fun(File) ->
+ lists:concat([Protocol,"://",Host,":",Port,"/",File])
end,
[{dummy_pid,Pid},{urlfun,F},{protocol,Protocol},{port,Port} | Config].
start_nginx(Protocol, Config) ->
PrivDir = ?config(priv_dir, Config),
DataDir = ?config(data_dir, Config),
- Host = ?config(server_host, Config),
+ Host = ?config(server_host, Config),
Port = inet_port(node()),
-
+
ConfFile = filename:join(PrivDir, "nginx.conf"),
nginx_conf(ConfFile, [{port, Port}, {protocol, Protocol} | Config]),
- Cmd = "nginx -c " ++ ConfFile,
- NginxPort = open_port({spawn, Cmd}, [{cd, DataDir}, stderr_to_stdout]),
+ Cmd = "nginx -c " ++ ConfFile,
+ NginxPort = open_port({spawn, Cmd}, [{cd, DataDir}, stderr_to_stdout]),
- F = fun(File) ->
- lists:concat([Protocol,"://",Host,":",Port,"/",File])
+ F = fun(File) ->
+ lists:concat([Protocol,"://",Host,":",Port,"/",File])
end,
-
+
wait_for_nginx_up(Host, Port),
-
+
[{port, Port},{nginx_port, NginxPort},{urlfun,F},{protocol, Protocol} | Config ].
stop_nginx(Config)->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
{ok, Bin} = file:read_file(filename:join(PrivDir, "nginx.pid")),
Pid = string:strip(binary_to_list(Bin), right, $\n),
Cmd = "kill " ++ Pid,
os:cmd(Cmd).
-
+
stop_web_server(Group, Config) when Group == http_inets;
Group == http_inets_keep_alive;
Group == https_inets;
- Group == https_inets_keep_alive ->
+ Group == https_inets_keep_alive ->
ServerNode = ?config(server_node, Config),
rpc:call(ServerNode, inets, stop, [httpd, ?config(httpd_pid, Config)]);
stop_web_server(Group, Config) when Group == http_dummy;
Group == http_dummy_keep_alive;
Group == https_dummy;
- Group == https_dummy_keep_alive ->
+ Group == https_dummy_keep_alive ->
stop_dummy_server(Config);
stop_web_server(Group, Config) when Group == http_nginx;
Group == http_nginx_keep_alive;
Group == https_nginx;
- Group == https_nginx_keep_alive ->
+ Group == https_nginx_keep_alive ->
stop_nginx(Config).
-stop_dummy_server(Config) ->
+stop_dummy_server(Config) ->
case ?config(dummy_pid, Config) of
Pid when is_pid(Pid) ->
exit(Pid, kill);
@@ -611,7 +635,7 @@ do_inet_port(Node) ->
{ok, Socket} = rpc:call(Node, gen_tcp, listen, [0, [{reuseaddr, true}]]),
{ok, Port} = rpc:call(Node, inet, port, [Socket]),
{Port, Socket}.
-
+
%%--------------------------------------------------------------------
%% Dummy server callbacks ------------------------------------------------
%%--------------------------------------------------------------------
@@ -630,18 +654,18 @@ do_handle_request(CB, S, Name, Opts, KeepAlive) when is_list(Name) ->
{ok, Fdesc} = file:open(Name, [read, binary]),
{ok, Info} = file:read_file_info(Name, []),
Length = Info#file_info.size,
- Response = response_status_line_and_headers(Version, "Content-Length:"
- ++ integer_to_list(Length) ++ ?CRLF, keep_alive(KeepAlive)),
+ Response = response_status_line_and_headers(Version, "Content-Length:"
+ ++ integer_to_list(Length) ++ ?CRLF, keep_alive(KeepAlive)),
CB:send(S, Response),
send_file(CB, S, Fdesc);
do_handle_request(CB, S, {gen, Data}, Opts, KeepAlive) ->
Version = proplists:get_value(http_version, Opts),
Length = byte_size(Data),
- Response = response_status_line_and_headers(Version, "Content-Length:"
- ++ integer_to_list(Length) ++ ?CRLF, keep_alive(KeepAlive)),
+ Response = response_status_line_and_headers(Version, "Content-Length:"
+ ++ integer_to_list(Length) ++ ?CRLF, keep_alive(KeepAlive)),
CB:send(S, Response),
send_file(CB, S, {gen, Data}).
-
+
send_file(CB, S, {gen, Data}) ->
CB:send(S, Data);
%% ChunkSize = 64*1024,
@@ -653,19 +677,19 @@ send_file(CB, S, {gen, Data}) ->
%% send_file(CB, S, {gen, Rest});
%% _ ->
%% CB:send(S, Data)
- %% end;
+ %% end;
send_file(CB, S, FileDesc) ->
case file:read(FileDesc, 64*1024) of
{ok, Chunk} ->
CB:send(S, Chunk),
- send_file(CB, S, FileDesc);
+ send_file(CB, S, FileDesc);
eof ->
file:close(FileDesc),
ok
end.
-response_status_line_and_headers(Version, Headers, ConnectionHeader) ->
+response_status_line_and_headers(Version, Headers, ConnectionHeader) ->
StatusLine = [Version, " ", "200 OK", ?CRLF],
[StatusLine, Headers, ConnectionHeader, ?CRLF].
@@ -682,8 +706,9 @@ handle_http_msg({_Method, RelUri, _, {_, _Headers}, _Body}, Socket, Conf) ->
false ->
stop
end.
-
-connect_cb({sslsocket, _, _}) ->
+
+%% arity has increased in later versions of OTP, not arity 3 anymore
+connect_cb(SSLSocket) when element(1, SSLSocket) =:= sslsocket ->
ssl;
connect_cb(_) ->
gen_tcp.
@@ -696,41 +721,37 @@ wget_req_file(FileName, Url, Iter) ->
write_urls(File, Url, Iter).
write_urls(File, Url, 1) ->
- file:write(File, Url),
+ file:write(File, Url),
file:close(File);
write_urls(File, Url, N) ->
- file:write(File, Url),
+ file:write(File, Url),
file:write(File, "\n"),
write_urls(File, Url, N-1).
-
+
wait_for_wget(Port) ->
- receive
+ receive
{Port, {data, _Data}} when is_port(Port) ->
wait_for_wget(Port);
- {Port, closed} ->
+ {Port, closed} ->
ok;
{'EXIT', Port, _Reason} ->
ok
end.
wget_N(KeepAlive, WegetFile, "http", _ProtocolOpts) ->
- "wget -i " ++ WegetFile ++ " " ++ wget_keep_alive(KeepAlive) ++
+ "wget -i " ++ WegetFile ++ " " ++ wget_keep_alive(KeepAlive) ++
" --no-cache --timeout=120" ;
wget_N(KeepAlive, WegetFile, "https", ProtocolOpts) ->
-
- "wget -i " ++ WegetFile ++ " " ++ wget_keep_alive(KeepAlive)
- ++ wget_cert(ProtocolOpts) ++ wget_key(ProtocolOpts)
- ++ wget_cacert(ProtocolOpts) ++
+ "wget -i " ++ WegetFile ++ " " ++ wget_keep_alive(KeepAlive)
+ ++ wget_cacert(ProtocolOpts) ++
" --no-cache --timeout=120".
wget(KeepAlive, URL, "http", _ProtocolOpts) ->
- "wget " ++ URL ++ " " ++ wget_keep_alive(KeepAlive) ++
+ "wget " ++ URL ++ " " ++ wget_keep_alive(KeepAlive) ++
" --no-cache --timeout=120" ;
wget(KeepAlive, URL, "https", ProtocolOpts) ->
-
- "wget " ++ URL ++ " " ++ wget_keep_alive(KeepAlive)
- ++ wget_cert(ProtocolOpts) ++ wget_key(ProtocolOpts)
- ++ wget_cacert(ProtocolOpts) ++
+ "wget " ++ URL ++ " " ++ wget_keep_alive(KeepAlive)
+ ++ wget_cacert(ProtocolOpts) ++
" --no-cache --timeout=120".
wget_keep_alive(true)->
@@ -741,27 +762,21 @@ wget_keep_alive(false) ->
wget_cacert(ProtocolOpts) ->
"--ca-certificate=" ++ proplists:get_value(cacertfile, ProtocolOpts) ++ " ".
-wget_cert(ProtocolOpts) ->
- "--certificate=" ++ proplists:get_value(certfile, ProtocolOpts) ++ " ".
-
-wget_key(ProtocolOpts) ->
- "--private-key=" ++ proplists:get_value(keyfile, ProtocolOpts) ++ " ".
-
%%--------------------------------------------------------------------
%% Setup nginx ------------------------------------------------
%%--------------------------------------------------------------------
-nginx_conf(ConfFile, Config)->
+nginx_conf(ConfFile, Config) ->
Protocol = ?config(protocol, Config),
file:write_file(ConfFile,
[format_nginx_conf(nginx_global(Config)),
format_nginx_conf(nginx_events(Config)),
format_nginx_conf(nginx_http(Protocol, Config))]).
-
+
format_nginx_conf(Directives) ->
lists:map(fun({Key, Value}) ->
io_lib:format("~s ~s;\n", [Key, Value]);
(Str) ->
- Str
+ Str
end, Directives).
@@ -784,13 +799,13 @@ nginx_http("http", Config) ->
["http {\n" |
nginx_defaults(PrivDir) ++
[" server {",
- {root, DataDir},
+ {root, DataDir},
{listen, integer_to_list(Port)},
" location / {\n try_files $uri $uri/ /index.html;\n}"
"}\n", "}\n"
]
];
-
+
nginx_http("https", Config) ->
PrivDir = ?config(priv_dir, Config),
DataDir = ?config(data_dir, Config),
@@ -801,24 +816,24 @@ nginx_http("https", Config) ->
["http {" |
nginx_defaults(PrivDir) ++
[" server {",
- {"root", DataDir},
+ {"root", DataDir},
{"listen", integer_to_list(Port) ++ " ssl"},
{"ssl_certificate", ?config(certfile, SSLOpts)},
{"ssl_certificate_key", ?config(keyfile, SSLOpts)},
{"ssl_protocols", "TLSv1 TLSv1.1 TLSv1.2"},
- {"ssl_ciphers", Ciphers},
+ {"ssl_ciphers", Ciphers},
{"ssl_session_cache", nginx_reuse_session(ReuseSession)},
" location / {\n try_files $uri $uri/ /index.html;\n}"
"}\n", "}\n"
]
].
-
+
nginx_defaults(PrivDir) ->
[
%% Set temp and cache file options that will otherwise default to
%% restricted locations accessible only to root.
{"client_body_temp_path", filename:join(PrivDir, "client_body")},
- {"fastcgi_temp_path", filename:join(PrivDir, "fastcgi_temp")},
+ {"fastcgi_temp_path", filename:join(PrivDir, "fastcgi_temp")},
{"proxy_temp_path", filename:join(PrivDir, "proxy_temp")},
{"scgi_temp_path", filename:join(PrivDir, "scgi_temp")},
{"uwsgi_temp_path", filename:join(PrivDir, "uwsgi_temp_path")},
@@ -847,4 +862,3 @@ wait_for_nginx_up(Host, Port) ->
ct:sleep(100),
wait_for_nginx_up(Host, Port)
end.
-
diff --git a/lib/inets/test/httpd_bench_certs.erl b/lib/inets/test/httpd_bench_certs.erl
new file mode 100644
index 0000000000..0c3940bfe8
--- /dev/null
+++ b/lib/inets/test/httpd_bench_certs.erl
@@ -0,0 +1,128 @@
+%%% %CopyrightBegin%
+%%%
+%%% SPDX-License-Identifier: Apache-2.0
+%%%
+%%% Copyright Ericsson AB 2025-2025. All Rights Reserved.
+%%%
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
+%%%
+%%% %CopyrightEnd%
+
+-module(httpd_bench_certs).
+
+-export([hardcode_rsa_key/1, choose_sha_function/0, der_to_pem/2, cert_entry/1,
+ key_entry/1, ca_entries/1, make_cert_files/1]).
+
+-include_lib("public_key/include/public_key.hrl").
+
+%% The subjectAltName extension is included and equal to net_adm:localhost() of the test host
+make_cert_files(Dir) ->
+ #{server_config := ServerConf,
+ client_config := _} = public_key:pkix_test_data(
+ #{server_chain =>
+ #{
+ root => [{key, hardcode_rsa_key(1)}, {digest, choose_sha_function()}],
+ intermediates => [[{key, hardcode_rsa_key(2)}, {digest, choose_sha_function()}]],
+ peer => [{key, hardcode_rsa_key(3)}, {digest, choose_sha_function()}]
+ },
+ client_chain =>
+ #{
+ root => [{key, hardcode_rsa_key(1)}, {digest, choose_sha_function()}],
+ intermediates => [[{key, hardcode_rsa_key(3)}, {digest, choose_sha_function()}]],
+ peer => [{key, hardcode_rsa_key(2)}, {digest, choose_sha_function()}]
+ }
+ }),
+
+ CaCertFile = filename:join([Dir, "server-cacerts.pem"]),
+ CertFile = filename:join([Dir, "server-cert.pem"]),
+ KeyFile = filename:join([Dir, "server-key.pem"]),
+
+ CAs = proplists:get_value(cacerts, ServerConf),
+ Cert = proplists:get_value(cert, ServerConf),
+ Key = proplists:get_value(key, ServerConf),
+ der_to_pem(CertFile, [cert_entry(Cert)]),
+ der_to_pem(KeyFile, [key_entry(Key)]),
+ der_to_pem(CaCertFile, ca_entries(CAs)).
+
+
+der_to_pem(File, Entries) ->
+ PemBin = public_key:pem_encode(Entries),
+ file:write_file(File, PemBin).
+
+
+choose_sha_function() ->
+ Hashes = proplists:get_value(hashs, crypto:supports()),
+ case os:cmd("openssl version") of
+ "OpenSSL 0.9.8" ++ _ -> sha;
+ _ ->
+ case lists:member(sha256, Hashes) of
+ true -> sha256;
+ false -> sha
+ end
+ end.
+
+
+cert_entry(Cert) ->
+ {'Certificate', Cert, not_encrypted}.
+
+
+key_entry({'RSAPrivateKey', DERKey}) ->
+ {'RSAPrivateKey', DERKey, not_encrypted};
+key_entry({'DSAPrivateKey', DERKey}) ->
+ {'DSAPrivateKey', DERKey, not_encrypted};
+key_entry({'ECPrivateKey', DERKey}) ->
+ {'ECPrivateKey', DERKey, not_encrypted}.
+
+
+ca_entries(CAs) ->
+ [{'Certificate', CACert, not_encrypted} || CACert <- CAs].
+
+
+hardcode_rsa_key(1) ->
+ #'RSAPrivateKey'{
+ version = 'two-prime',
+ modulus = 23995666614853919027835084074500048897452890537492185072956789802729257783422306095699263934587064480357348855732149402060270996295002843755712064937715826848741191927820899197493902093529581182351132392364214171173881547273475904587683433713767834856230531387991145055273426806331200574039205571401702219159773947658558490957010003143162250693492642996408861265758000254664396313741422909188635443907373976005987612936763564996605457102336549804831742940035613780926178523017685712710473543251580072875247250504243621640157403744718833162626193206685233710319205099867303242759099560438381385658382486042995679707669,
+ publicExponent = 17,
+ privateExponent = 11292078406990079542510627799764728892919007311761028269626724613049062486316379339152594792746853873109340637991599718616598115903530750002688030558925094987642913848386305504703012749896273497577003478759630198199473669305165131570674557041773098755873191241407597673069847908861741446606684974777271632545629600685952292605647052193819136445675100211504432575554351515262198132231537860917084269870590492135731720141577986787033006338680118008484613510063003323516659048210893001173583018220214626635609151105287049126443102976056146630518124476470236027123782297108342869049542023328584384300970694412006494684657,
+ prime1 = 169371138592582642967021557955633494538845517070305333860805485424261447791289944610138334410987654265476540480228705481960508520379619587635662291973699651583489223555422528867090299996446070521801757353675026048850480903160224210802452555900007597342687137394192939372218903554801584969667104937092080815197,
+ prime2 = 141675062317286527042995673340952251894209529891636708844197799307963834958115010129693036021381525952081167155681637592199810112261679449166276939178032066869788822014115556349519329537177920752776047051833616197615329017439297361972726138285974555338480581117881706656603857310337984049152655480389797687577,
+ exponent1 = 119556097830058336212015217380447172615655659108450823901745048534772786676204666783627059584226579481512852103690850928442711896738555003036938088452023283470698275450886490965004917644550167427154181661417665446247398284583687678213495921811770068712485038160606780733330990744565824684470897602653233516609,
+ exponent2 = 41669135975672507953822256864985956439473391144599032012999352737636422046504414744027363535700448809435637398729893409470532385959317485048904982111185902020526124121798693043976273393287623750816484427009887116945685005129205106462566511260580751570141347387612266663707016855981760014456663376585234613993,
+ coefficient = 76837684977089699359024365285678488693966186052769523357232308621548155587515525857011429902602352279058920284048929101483304120686557782043616693940283344235057989514310975192908256494992960578961614059245280827077951132083993754797053182279229469590276271658395444955906108899267024101096069475145863928441,
+ otherPrimeInfos = asn1_NOVALUE};
+
+hardcode_rsa_key(2) ->
+ #'RSAPrivateKey'{
+ version = 'two-prime',
+ modulus = 21343679768589700771839799834197557895311746244621307033143551583788179817796325695589283169969489517156931770973490560582341832744966317712674900833543896521418422508485833901274928542544381247956820115082240721897193055368570146764204557110415281995205343662628196075590438954399631753508888358737971039058298703003743872818150364935790613286541190842600031570570099801682794056444451081563070538409720109449780410837763602317050353477918147758267825417201591905091231778937606362076129350476690460157227101296599527319242747999737801698427160817755293383890373574621116766934110792127739174475029121017282777887777,
+ publicExponent = 17,
+ privateExponent = 18832658619343853622211588088997845201745658451136447382185486691577805721584993260814073385267196632785528033211903435807948675951440868570007265441362261636545666919252206383477878125774454042314841278013741813438699754736973658909592256273895837054592950290554290654932740253882028017801960316533503857992358685308186680144968293076156011747178275038098868263178095174694099811498968993700538293188879611375604635940554394589807673542938082281934965292051746326331046224291377703201248790910007232374006151098976879987912446997911775904329728563222485791845480864283470332826504617837402078265424772379987120023773,
+ prime1 = 146807662748886761089048448970170315054939768171908279335181627815919052012991509112344782731265837727551849787333310044397991034789843793140419387740928103541736452627413492093463231242466386868459637115999163097726153692593711599245170083315894262154838974616739452594203727376460632750934355508361223110419,
+ prime2 = 145385325050081892763917667176962991350872697916072592966410309213561884732628046256782356731057378829876640317801978404203665761131810712267778698468684631707642938779964806354584156202882543264893826268426566901882487709510744074274965029453915224310656287149777603803201831202222853023280023478269485417083,
+ exponent1 = 51814469205489445090252393754177758254684624060673510353593515699736136004585238510239335081623236845018299924941168250963996835808180162284853901555621683602965806809675350150634081614988136541809283687999704622726877773856604093851236499993845033701707873394143336209718962603456693912094478414715725803677,
+ exponent2 = 51312467664734785681382706062457526359131540440966797517556579722433606376221663384746714140373192528191755406283051201483646739222992016094510128871300458249756331334105225772206172777487956446433115153562317730076172132768497908567634716277852432109643395464627389577600646306666889302334125933506877206029,
+ coefficient = 30504662229874176232343608562807118278893368758027179776313787938167236952567905398252901545019583024374163153775359371298239336609182249464886717948407152570850677549297935773605431024166978281486607154204888016179709037883348099374995148481968169438302456074511782717758301581202874062062542434218011141540,
+ otherPrimeInfos = asn1_NOVALUE};
+
+hardcode_rsa_key(3) ->
+ #'RSAPrivateKey'{
+ version = 'two-prime',
+ modulus = 25089040456112869869472694987833070928503703615633809313972554887193090845137746668197820419383804666271752525807484521370419854590682661809972833718476098189250708650325307850184923546875260207894844301992963978994451844985784504212035958130279304082438876764367292331581532569155681984449177635856426023931875082020262146075451989132180409962870105455517050416234175675478291534563995772675388370042873175344937421148321291640477650173765084699931690748536036544188863178325887393475703801759010864779559318631816411493486934507417755306337476945299570726975433250753415110141783026008347194577506976486290259135429,
+ publicExponent = 17,
+ privateExponent = 8854955455098659953931539407470495621824836570223697404931489960185796768872145882893348383311931058684147950284994536954265831032005645344696294253579799360912014817761873358888796545955974191021709753644575521998041827642041589721895044045980930852625485916835514940558187965584358347452650930302268008446431977397918214293502821599497633970075862760001650736520566952260001423171553461362588848929781360590057040212831994258783694027013289053834376791974167294527043946669963760259975273650548116897900664646809242902841107022557239712438496384819445301703021164043324282687280801738470244471443835900160721870265,
+ prime1 = 171641816401041100605063917111691927706183918906535463031548413586331728772311589438043965564336865070070922328258143588739626712299625805650832695450270566547004154065267940032684307994238248203186986569945677705100224518137694769557564475390859269797990555863306972197736879644001860925483629009305104925823,
+ prime2 = 146170909759497809922264016492088453282310383272504533061020897155289106805616042710009332510822455269704884883705830985184223718261139908416790475825625309815234508695722132706422885088219618698987115562577878897003573425367881351537506046253616435685549396767356003663417208105346307649599145759863108910523,
+ exponent1 = 60579464612132153154728441333538327425711971378777222246428851853999433684345266860486105493295364142377972586444050678378691780811632637288529186629507258781295583787741625893888579292084087601124818789392592131211843947578009918667375697196773859928702549128225990187436545756706539150170692591519448797349,
+ exponent2 = 137572620950115585809189662580789132500998007785886619351549079675566218169991569609420548245479957900898715184664311515467504676010484619686391036071176762179044243478326713135456833024206699951987873470661533079532774988581535389682358631768109586527575902839864474036157372334443583670210960715165278974609,
+ coefficient = 15068630434698373319269196003209754243798959461311186548759287649485250508074064775263867418602372588394608558985183294561315208336731894947137343239541687540387209051236354318837334154993136528453613256169847839789803932725339395739618592522865156272771578671216082079933457043120923342632744996962853951612,
+ otherPrimeInfos = asn1_NOVALUE}.
diff --git a/lib/inets/test/inets.spec b/lib/inets/test/inets.spec
index 027b0f1630..b12b699624 100644
--- a/lib/inets/test/inets.spec
+++ b/lib/inets/test/inets.spec
@@ -1,6 +1,25 @@
+%%
+%% %CopyrightBegin%
+%%
+%% SPDX-License-Identifier: Apache-2.0
+%%
+%% Copyright Ericsson AB 2012-2025. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
{suites,"../inets_test", all}.
-{skip_suites, "../inets_test", [httpd_bench_SUITE],
- "Benchmarks run separately"}.
{event_handler, {cte_track, []}}.
{enable_builtin_hooks, false}.
{ct_hooks, [{cth_log_redirect, [{mode, replace}]}]}.
diff --git a/lib/inets/test/inets_test_lib.erl b/lib/inets/test/inets_test_lib.erl
index 27521ef7e8..796b2e1c20 100644
--- a/lib/inets/test/inets_test_lib.erl
+++ b/lib/inets/test/inets_test_lib.erl
@@ -36,10 +36,10 @@ has_ipv6_support() ->
tsp("has_ipv6_support -> no ipv6_hosts config"),
{ok, Hostname} = inet:gethostname(),
case inet:getaddrs(Hostname, inet6) of
- {ok, [Addr|_]} when is_tuple(Addr) andalso
+ {ok, [Addr|_]} when is_tuple(Addr) andalso
(element(1, Addr) =/= 0) ->
- %% We actually need to test that the addr can be used,
- %% this is done by attempting to create a (tcp)
+ %% We actually need to test that the addr can be used,
+ %% this is done by attempting to create a (tcp)
%% listen socket
tsp("has_ipv6_support -> check Addr: ~p", [Addr]),
case (catch gen_tcp:listen(0, [inet6, {ip, Addr}])) of
@@ -53,11 +53,11 @@ has_ipv6_support() ->
_ ->
undefined
end.
-
+
has_ipv6_support(Config) ->
case lists:keysearch(ipv6_hosts, 1, Config) of
false ->
- %% Do a basic check to se if
+ %% Do a basic check to se if
%% our own host has a working IPv6 address...
has_ipv6_support();
@@ -73,7 +73,7 @@ has_ipv6_support(Config) ->
false ->
undefined
end;
-
+
_ ->
undefined
@@ -86,7 +86,7 @@ oscmd(Cmd) ->
print_system_info([]) ->
do_print_system_info("System Info");
print_system_info(Prefix) when is_list(Prefix) ->
- NewPrefix = lists:flatten(io_lib:format("~s: System Info", [Prefix])),
+ NewPrefix = lists:flatten(io_lib:format("~s: System Info", [Prefix])),
do_print_system_info(NewPrefix).
do_print_system_info(Prefix) ->
@@ -101,8 +101,8 @@ do_print_system_info(Prefix) ->
"~n Num schedulers: ~p"
"~n Scheduler bindings: ~p"
"~n Wordsize: ~p"
- "~n~n", [Prefix,
- os:type(), os:version(),
+ "~n~n", [Prefix,
+ os:type(), os:version(),
erlang:system_info(system_architecture),
erlang:system_info(cpu_topology),
erlang:system_info(logical_processors),
@@ -111,8 +111,8 @@ do_print_system_info(Prefix) ->
erlang:system_info(scheduler_bindings),
erlang:system_info(wordsize)]),
ok.
-
-
+
+
run_on_windows(Fun) ->
run_on_os(windows, Fun).
@@ -123,8 +123,8 @@ run_on_os(windows, Fun) ->
_ ->
ok
end.
-
-
+
+
%% -- Misc node operation wrapper functions --
start_node(Name) ->
@@ -139,7 +139,7 @@ start_node(Name) ->
end,
A = Args ++ " -pa " ++ Pa,
Opts = [{cleanup,false}, {args, A}],
- case (catch test_server:start_node(Name, slave, Opts)) of
+ case (catch test_server:start_node(Name, peer, Opts)) of
{ok, Node} ->
Node;
Else ->
@@ -165,7 +165,7 @@ await_stopped(Node, N) ->
%% ----------------------------------------------------------------
%% Ensure apps are started
-%% This to ensure we dont attempt to run teatcases on platforms
+%% This to ensure we dont attempt to run teatcases on platforms
%% where there is no working ssl app.
ensure_started([]) ->
@@ -174,9 +174,9 @@ ensure_started([App|Apps]) ->
ensure_started(App),
ensure_started(Apps);
ensure_started(crypto = App) ->
- %% We have to treat crypto in this special way because
+ %% We have to treat crypto in this special way because
%% only this function ensures that the NIF lib is actually
- %% loaded. And only by loading that lib can we know if it
+ %% loaded. And only by loading that lib can we know if it
%% is even possible to run crypto.
do_ensure_started(App, fun() -> application:start(crypto) end);
ensure_started(App) when is_atom(App) ->
@@ -214,9 +214,9 @@ start_http_server(Conf) ->
start_http_server(Conf, ssl = _SslTag) ->
tsp("start_http_server(ssl) -> try start crypto"),
- application:start(crypto),
+ application:start(crypto),
tsp("start_http_server(ssl) -> try start public_key"),
- application:start(public_key),
+ application:start(public_key),
do_start_http_server(Conf);
start_http_server(Conf, SslTag) ->
tsp("start_http_server(~w) -> entry", [SslTag]),
@@ -253,12 +253,12 @@ do_start_http_server(Conf) ->
"~n Reason: ~p", [Reason]),
tsf({failed_loading_inets, Reason})
end.
-
+
start_http_server_ssl(FileName) ->
start_http_server_ssl(FileName, ssl).
start_http_server_ssl(FileName, ssl = _SslTag) ->
- application:start(crypto),
+ application:start(crypto),
do_start_http_server_ssl(FileName);
start_http_server_ssl(FileName, _SslTag) ->
do_start_http_server_ssl(FileName).
@@ -267,7 +267,7 @@ do_start_http_server_ssl(FileName) ->
tsp("start (ssl) http server with "
"~n FileName: ~p"
"~n", [FileName]),
- application:start(ssl),
+ application:start(ssl),
catch do_start_http_server(FileName).
@@ -303,9 +303,9 @@ from(_, []) -> [].
copy_file(File, From, To) ->
file:copy(filename:join(From, File), filename:join(To, File)).
-copy_files(FromDir, ToDir) ->
+copy_files(FromDir, ToDir) ->
{ok, Files} = file:list_dir(FromDir),
- lists:foreach(fun(File) ->
+ lists:foreach(fun(File) ->
FullPath = filename:join(FromDir, File),
case filelib:is_file(FullPath) of
true ->
@@ -321,9 +321,9 @@ copy_dirs(FromDirRoot, ToDirRoot) ->
case file:list_dir(FromDirRoot) of
{ok, Files} ->
lists:foreach(
- fun(FileOrDir) ->
+ fun(FileOrDir) ->
%% Check if it's a directory or a file
- case filelib:is_dir(filename:join(FromDirRoot,
+ case filelib:is_dir(filename:join(FromDirRoot,
FileOrDir)) of
true ->
FromDir = filename:join([FromDirRoot, FileOrDir]),
@@ -337,10 +337,10 @@ copy_dirs(FromDirRoot, ToDirRoot) ->
"~n Reason: ~p"
"~nwhen"
"~n ToDirRoot: ~p"
- "~n ToDirRoot file info: ~p",
- [ToDir,
- Reason,
- ToDirRoot,
+ "~n ToDirRoot file info: ~p",
+ [ToDir,
+ Reason,
+ ToDirRoot,
file:read_file_info(ToDirRoot)]),
tsf({failed_copy_dir, ToDir, Reason})
end;
@@ -353,14 +353,14 @@ copy_dirs(FromDirRoot, ToDirRoot) ->
"~n FromDirRoot: ~p"
"~n Reason: ~p"
"~nwhen"
- "~n FromDirRoot file info: ~p",
- [FromDirRoot,
- Reason,
+ "~n FromDirRoot file info: ~p",
+ [FromDirRoot,
+ Reason,
file:read_file_info(FromDirRoot)]),
tsf({failed_list_dir, FromDirRoot, Reason})
end.
-
-
+
+
del_dirs(Dir) ->
case file:list_dir(Dir) of
@@ -372,10 +372,10 @@ del_dirs(Dir) ->
case filelib:is_dir(FullPath) of
true ->
del_dirs(FullPath),
- file:del_dir(FullPath);
+ file:del_dir(FullPath);
false ->
file:delete(FullPath)
- end
+ end
end, Files);
_ ->
ok
@@ -453,7 +453,7 @@ os_based_skip(_) ->
%% Socket functions:
%% open(SocketType, Host, Port) -> {ok, Socket} | {error, Reason}
%% SocketType -> ssl | ip_comm
-%% Host -> atom() | string() | {A, B, C, D}
+%% Host -> atom() | string() | {A, B, C, D}
%% Port -> integer()
connect_bin(SockType, Host, Port) ->
@@ -470,7 +470,7 @@ connect_bin(Type, Host, Port, Opts) ->
connect_byte(SockType, Host, Port) ->
connect_byte(SockType, Host, Port, []).
-
+
connect_byte(ssl, Host, Port, Opts0) ->
Opts = [list, {packet,0}, {verify, verify_none} | Opts0],
connect(ssl, Host, Port, Opts);
@@ -486,7 +486,7 @@ connect(ssl, Host, Port, Opts) ->
ssl:connect(Host, Port, Opts);
connect(openssl_port, Host, Port, Opts) ->
CaCertFile = proplists:get_value(cacertfile, Opts),
- Cmd = "openssl s_client -quiet -port " ++ integer_to_list(Port) ++ " -host " ++ Host
+ Cmd = "openssl s_client -quiet -port " ++ integer_to_list(Port) ++ " -host " ++ Host
++ " -CAfile " ++ CaCertFile,
ct:log("openssl cmd: ~p~n", [Cmd]),
OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
@@ -549,7 +549,7 @@ tsp(F) ->
tsp(F, []).
tsp(F, A) ->
Timestamp = inets_lib:formated_timestamp(),
- ct:log("*** ~s ~p ~p " ++ F ++ "~n",
+ ct:log("*** ~s ~p ~p " ++ F ++ "~n",
[Timestamp, node(), self() | A]).
tsf(Reason) ->
@@ -585,8 +585,8 @@ read_junk(OpensslPort) ->
receive
{OpensslPort, _} ->
read_junk(OpensslPort)
- after 500 ->
- ok
+ after 500 ->
+ ok
end.
hardcode_rsa_key(1) ->
#'RSAPrivateKey'{
@@ -613,8 +613,8 @@ hardcode_rsa_key(2) ->
exponent2 = 51312467664734785681382706062457526359131540440966797517556579722433606376221663384746714140373192528191755406283051201483646739222992016094510128871300458249756331334105225772206172777487956446433115153562317730076172132768497908567634716277852432109643395464627389577600646306666889302334125933506877206029,
coefficient = 30504662229874176232343608562807118278893368758027179776313787938167236952567905398252901545019583024374163153775359371298239336609182249464886717948407152570850677549297935773605431024166978281486607154204888016179709037883348099374995148481968169438302456074511782717758301581202874062062542434218011141540,
otherPrimeInfos = asn1_NOVALUE};
-hardcode_rsa_key(3) ->
- #'RSAPrivateKey'{
+hardcode_rsa_key(3) ->
+ #'RSAPrivateKey'{
version = 'two-prime',
modulus = 25089040456112869869472694987833070928503703615633809313972554887193090845137746668197820419383804666271752525807484521370419854590682661809972833718476098189250708650325307850184923546875260207894844301992963978994451844985784504212035958130279304082438876764367292331581532569155681984449177635856426023931875082020262146075451989132180409962870105455517050416234175675478291534563995772675388370042873175344937421148321291640477650173765084699931690748536036544188863178325887393475703801759010864779559318631816411493486934507417755306337476945299570726975433250753415110141783026008347194577506976486290259135429,
publicExponent = 17,
@@ -625,7 +625,7 @@ hardcode_rsa_key(3) ->
exponent2 = 137572620950115585809189662580789132500998007785886619351549079675566218169991569609420548245479957900898715184664311515467504676010484619686391036071176762179044243478326713135456833024206699951987873470661533079532774988581535389682358631768109586527575902839864474036157372334443583670210960715165278974609,
coefficient = 15068630434698373319269196003209754243798959461311186548759287649485250508074064775263867418602372588394608558985183294561315208336731894947137343239541687540387209051236354318837334154993136528453613256169847839789803932725339395739618592522865156272771578671216082079933457043120923342632744996962853951612,
otherPrimeInfos = asn1_NOVALUE};
-hardcode_rsa_key(4) ->
+hardcode_rsa_key(4) ->
#'RSAPrivateKey'{
version ='two-prime',
modulus = 28617237755030755643854803617273584643843067580642149032833640135949799721163782522787597288521902619948688786051081993247908700824196122780349730169173433743054172191054872553484065655968335396052034378669869864779940355219732200954630251223541048434478476115391643898092650304645086338265930608997389611376417609043761464100338332976874588396803891301015812818307951159858145399281035705713082131199940309445719678087542976246147777388465712394062188801177717719764254900022006288880246925156931391594131839991579403409541227225173269459173129377291869028712271737734702830877034334838181789916127814298794576266389,
@@ -638,8 +638,8 @@ hardcode_rsa_key(4) ->
coefficient = 34340318160575773065401929915821192439103777558577109939078671096408836197675640654693301707202885840826672396546056002756167635035389371579540325327619480512374920136684787633921441576901246290213545161954865184290700344352088099063404416346968182170720521708773285279884132629954461545103181082503707725012,
otherPrimeInfos = asn1_NOVALUE};
-hardcode_rsa_key(5) ->
- #'RSAPrivateKey'{
+hardcode_rsa_key(5) ->
+ #'RSAPrivateKey'{
version= 'two-prime',
modulus = 26363170152814518327068346871197765236382539835597898797762992537312221863402655353436079974302838986536256364057947538018476963115004626096654613827403121905035011992899481598437933532388248462251770039307078647864188314916665766359828262009578648593031111569685489178543405615478739906285223620987558499488359880003693226535420421293716164794046859453204135383236667988765227190694994861629971618548127529849059769249520775574008363789050621665120207265361610436965088511042779948238320901918522125988916609088415989475825860046571847719492980547438560049874493788767083330042728150253120940100665370844282489982633,
publicExponent = 17,
@@ -650,8 +650,8 @@ hardcode_rsa_key(5) ->
exponent2 = 142217122612346975946270932667689342506994371754500301644129838613240401623123353990351915239791856753802128921507833848784693455415929352968108818884760967629866396887841730408713142977345151214275311532385308673155315337734838428569962298621720191411498579097539089047726042088382891468987379296661520434973,
coefficient = 40624877259097915043489529504071755460170951428490878553842519165800720914888257733191322215286203357356050737713125202129282154441426952501134581314792133018830748896123382106683994268028624341502298766844710276939303555637478596035491641473828661569958212421472263269629366559343208764012473880251174832392,
otherPrimeInfos = asn1_NOVALUE};
-hardcode_rsa_key(6) ->
- #'RSAPrivateKey'{
+hardcode_rsa_key(6) ->
+ #'RSAPrivateKey'{
version = 'two-prime',
modulus = 22748888494866396715768692484866595111939200209856056370972713870125588774286266397044592487895293134537316190976192161177144143633669641697309689280475257429554879273045671863645233402796222694405634510241820106743648116753479926387434021380537483429927516962909367257212902212159798399531316965145618774905828756510318897899298783143203190245236381440043169622358239226123652592179006905016804587837199618842875361941208299410035232803124113612082221121192550063791073372276763648926636149384299189072950588522522800393261949880796214514243704858378436010975184294077063518776479282353562934591448646412389762167039,
publicExponent = 17,
@@ -665,11 +665,11 @@ hardcode_rsa_key(6) ->
gen_pem_config_files(#{server_config := ServerConf,
client_config := ClientConf}, ClientBase, ServerBase) ->
-
+
ServerCaCertFile = ServerBase ++ "_server_cacerts.pem",
ServerCertFile = ServerBase ++ "_server_cert.pem",
ServerKeyFile = ServerBase ++ "_server_key.pem",
-
+
ClientCaCertFile = ClientBase ++ "_client_cacerts.pem",
ClientCertFile = ClientBase ++ "_client_cert.pem",
ClientKeyFile = ClientBase ++ "_client_key.pem",
@@ -677,13 +677,13 @@ gen_pem_config_files(#{server_config := ServerConf,
do_gen_pem_config_files(ServerConf,
ServerCertFile,
ServerKeyFile,
- ServerCaCertFile),
+ ServerCaCertFile),
do_gen_pem_config_files(ClientConf,
ClientCertFile,
ClientKeyFile,
ClientCaCertFile),
- [{server_config, [{certfile, ServerCertFile},
- {keyfile, ServerKeyFile}, {cacertfile, ServerCaCertFile}]},
+ [{server_config, [{certfile, ServerCertFile},
+ {keyfile, ServerKeyFile}, {cacertfile, ServerCaCertFile}]},
{client_config, [{certfile, ClientCertFile},
{keyfile, ClientKeyFile}, {cacertfile, ClientCaCertFile}]}].
extensions(Exts) ->
@@ -719,7 +719,7 @@ extension({basic_constraints, Data}) ->
#'Extension'{extnID = ?'id-ce-basicConstraints',
extnValue = #'BasicConstraints'{cA=true},
critical=true};
- false ->
+ false ->
[];
Len when is_integer(Len) ->
#'Extension'{extnID = ?'id-ce-basicConstraints',
diff --git a/lib/inets/test/make_certs.erl b/lib/inets/test/make_certs.erl
deleted file mode 100644
index cc2db5158c..0000000000
--- a/lib/inets/test/make_certs.erl
+++ /dev/null
@@ -1,533 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% SPDX-License-Identifier: Apache-2.0
-%%
-%% Copyright Ericsson AB 2007-2025. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
--module(make_certs).
--compile([export_all]).
--compile(nowarn_export_all).
-
-%-export([all/1, all/2, rootCA/2, intermediateCA/3, endusers/3, enduser/3, revoke/3, gencrl/2, verify/3]).
-
--record(config, {commonName,
- organizationalUnitName = "Erlang OTP",
- organizationName = "Ericsson AB",
- localityName = "Stockholm",
- countryName = "SE",
- emailAddress = "peter@erix.ericsson.se",
- default_bits = 2048,
- v2_crls = true,
- ecc_certs = false,
- issuing_distribution_point = false,
- crl_port = 8000,
- openssl_cmd = "openssl"}).
-
-
-default_config() ->
- #config{}.
-
-make_config(Args) ->
- make_config(Args, #config{}).
-
-make_config([], C) ->
- C;
-make_config([{organizationalUnitName, Name}|T], C) when is_list(Name) ->
- make_config(T, C#config{organizationalUnitName = Name});
-make_config([{organizationName, Name}|T], C) when is_list(Name) ->
- make_config(T, C#config{organizationName = Name});
-make_config([{localityName, Name}|T], C) when is_list(Name) ->
- make_config(T, C#config{localityName = Name});
-make_config([{countryName, Name}|T], C) when is_list(Name) ->
- make_config(T, C#config{countryName = Name});
-make_config([{emailAddress, Name}|T], C) when is_list(Name) ->
- make_config(T, C#config{emailAddress = Name});
-make_config([{default_bits, Bits}|T], C) when is_integer(Bits) ->
- make_config(T, C#config{default_bits = Bits});
-make_config([{v2_crls, Bool}|T], C) when is_boolean(Bool) ->
- make_config(T, C#config{v2_crls = Bool});
-make_config([{crl_port, Port}|T], C) when is_integer(Port) ->
- make_config(T, C#config{crl_port = Port});
-make_config([{ecc_certs, Bool}|T], C) when is_boolean(Bool) ->
- make_config(T, C#config{ecc_certs = Bool});
-make_config([{issuing_distribution_point, Bool}|T], C) when is_boolean(Bool) ->
- make_config(T, C#config{issuing_distribution_point = Bool});
-make_config([{openssl_cmd, Cmd}|T], C) when is_list(Cmd) ->
- make_config(T, C#config{openssl_cmd = Cmd}).
-
-
-all([DataDir, PrivDir]) ->
- all(DataDir, PrivDir).
-
-all(DataDir, PrivDir) ->
- all(DataDir, PrivDir, #config{}).
-
-all(DataDir, PrivDir, C) when is_list(C) ->
- all(DataDir, PrivDir, make_config(C));
-all(DataDir, PrivDir, C = #config{}) ->
- ok = filelib:ensure_dir(filename:join(PrivDir, "erlangCA")),
- create_rnd(DataDir, PrivDir), % For all requests
- rootCA(PrivDir, "erlangCA", C),
- intermediateCA(PrivDir, "otpCA", "erlangCA", C),
- endusers(PrivDir, "otpCA", ["client", "server", "revoked", "a.server", "b.server"], C),
- endusers(PrivDir, "erlangCA", ["localhost"], C),
- %% Create keycert files
- SDir = filename:join([PrivDir, "server"]),
- SC = filename:join([SDir, "cert.pem"]),
- SK = filename:join([SDir, "key.pem"]),
- SKC = filename:join([SDir, "keycert.pem"]),
- append_files([SK, SC], SKC),
- CDir = filename:join([PrivDir, "client"]),
- CC = filename:join([CDir, "cert.pem"]),
- CK = filename:join([CDir, "key.pem"]),
- CKC = filename:join([CDir, "keycert.pem"]),
- append_files([CK, CC], CKC),
- RDir = filename:join([PrivDir, "revoked"]),
- RC = filename:join([RDir, "cert.pem"]),
- RK = filename:join([RDir, "key.pem"]),
- RKC = filename:join([RDir, "keycert.pem"]),
- revoke(PrivDir, "otpCA", "revoked", C),
- append_files([RK, RC], RKC),
- remove_rnd(PrivDir),
- {ok, C}.
-
-append_files(FileNames, ResultFileName) ->
- {ok, ResultFile} = file:open(ResultFileName, [write]),
- do_append_files(FileNames, ResultFile).
-
-do_append_files([], RF) ->
- ok = file:close(RF);
-do_append_files([F|Fs], RF) ->
- {ok, Data} = file:read_file(F),
- ok = file:write(RF, Data),
- do_append_files(Fs, RF).
-
-rootCA(Root, Name, C) ->
- create_ca_dir(Root, Name, ca_cnf(C#config{commonName = Name})),
- create_self_signed_cert(Root, Name, req_cnf(C#config{commonName = Name}), C),
- file:copy(filename:join([Root, Name, "cert.pem"]), filename:join([Root, Name, "cacerts.pem"])),
- gencrl(Root, Name, C).
-
-intermediateCA(Root, CA, ParentCA, C) ->
- create_ca_dir(Root, CA, ca_cnf(C#config{commonName = CA})),
- CARoot = filename:join([Root, CA]),
- CnfFile = filename:join([CARoot, "req.cnf"]),
- file:write_file(CnfFile, req_cnf(C#config{commonName = CA})),
- KeyFile = filename:join([CARoot, "private", "key.pem"]),
- ReqFile = filename:join([CARoot, "req.pem"]),
- create_req(Root, CnfFile, KeyFile, ReqFile, C),
- CertFile = filename:join([CARoot, "cert.pem"]),
- sign_req(Root, ParentCA, "ca_cert", ReqFile, CertFile, C),
- CACertsFile = filename:join(CARoot, "cacerts.pem"),
- file:copy(filename:join([Root, ParentCA, "cacerts.pem"]), CACertsFile),
- %% append this CA's cert to the cacerts file
- {ok, Bin} = file:read_file(CertFile),
- {ok, FD} = file:open(CACertsFile, [append]),
- file:write(FD, ["\n", Bin]),
- file:close(FD),
- gencrl(Root, CA, C).
-
-endusers(Root, CA, Users, C) ->
- [enduser(Root, CA, User, C) || User <- Users].
-
-enduser(Root, CA, User, C) ->
- UsrRoot = filename:join([Root, User]),
- file:make_dir(UsrRoot),
- CnfFile = filename:join([UsrRoot, "req.cnf"]),
- file:write_file(CnfFile, req_cnf(C#config{commonName = User})),
- KeyFile = filename:join([UsrRoot, "key.pem"]),
- ReqFile = filename:join([UsrRoot, "req.pem"]),
- create_req(Root, CnfFile, KeyFile, ReqFile, C),
- %create_req(Root, CnfFile, KeyFile, ReqFile),
- CertFileAllUsage = filename:join([UsrRoot, "cert.pem"]),
- sign_req(Root, CA, "user_cert", ReqFile, CertFileAllUsage, C),
- CertFileDigitalSigOnly = filename:join([UsrRoot, "digital_signature_only_cert.pem"]),
- sign_req(Root, CA, "user_cert_digital_signature_only", ReqFile, CertFileDigitalSigOnly, C),
- CACertsFile = filename:join(UsrRoot, "cacerts.pem"),
- file:copy(filename:join([Root, CA, "cacerts.pem"]), CACertsFile),
- ok.
-
-revoke(Root, CA, User, C) ->
- UsrCert = filename:join([Root, User, "cert.pem"]),
- CACnfFile = filename:join([Root, CA, "ca.cnf"]),
- Cmd = [C#config.openssl_cmd, " ca"
- " -revoke ", UsrCert,
- [" -crl_reason keyCompromise" || C#config.v2_crls ],
- " -config ", CACnfFile],
- Env = [{"ROOTDIR", filename:absname(Root)}],
- cmd(Cmd, Env),
- gencrl(Root, CA, C).
-
-gencrl(Root, CA, C) ->
- CACnfFile = filename:join([Root, CA, "ca.cnf"]),
- CACRLFile = filename:join([Root, CA, "crl.pem"]),
- Cmd = [C#config.openssl_cmd, " ca"
- " -gencrl ",
- " -crlhours 24",
- " -out ", CACRLFile,
- " -config ", CACnfFile],
- Env = [{"ROOTDIR", filename:absname(Root)}],
- cmd(Cmd, Env).
-
-verify(Root, CA, User, C) ->
- CAFile = filename:join([Root, User, "cacerts.pem"]),
- CACRLFile = filename:join([Root, CA, "crl.pem"]),
- CertFile = filename:join([Root, User, "cert.pem"]),
- Cmd = [C#config.openssl_cmd, " verify"
- " -CAfile ", CAFile,
- " -CRLfile ", CACRLFile, %% this is undocumented, but seems to work
- " -crl_check ",
- CertFile],
- Env = [{"ROOTDIR", filename:absname(Root)}],
- try cmd(Cmd, Env) catch
- exit:{eval_cmd, _, _} ->
- invalid
- end.
-
-create_self_signed_cert(Root, CAName, Cnf, C = #config{ecc_certs = true}) ->
- CARoot = filename:join([Root, CAName]),
- CnfFile = filename:join([CARoot, "req.cnf"]),
- file:write_file(CnfFile, Cnf),
- KeyFile = filename:join([CARoot, "private", "key.pem"]),
- CertFile = filename:join([CARoot, "cert.pem"]),
- Cmd = [C#config.openssl_cmd, " ecparam"
- " -out ", KeyFile,
- " -name secp521r1 ",
- %" -name sect283k1 ",
- " -genkey "],
- Env = [{"ROOTDIR", filename:absname(Root)}],
- cmd(Cmd, Env),
-
- Cmd2 = [C#config.openssl_cmd, " req"
- " -new"
- " -x509"
- " -config ", CnfFile,
- " -key ", KeyFile,
- " -outform PEM ",
- " -out ", CertFile],
- cmd(Cmd2, Env);
-create_self_signed_cert(Root, CAName, Cnf, C) ->
- CARoot = filename:join([Root, CAName]),
- CnfFile = filename:join([CARoot, "req.cnf"]),
- file:write_file(CnfFile, Cnf),
- KeyFile = filename:join([CARoot, "private", "key.pem"]),
- CertFile = filename:join([CARoot, "cert.pem"]),
- Cmd = [C#config.openssl_cmd, " req"
- " -new"
- " -x509"
- " -config ", CnfFile,
- " -keyout ", KeyFile,
- " -outform PEM",
- " -out ", CertFile],
- Env = [{"ROOTDIR", filename:absname(Root)}],
- cmd(Cmd, Env).
-
-
-create_ca_dir(Root, CAName, Cnf) ->
- CARoot = filename:join([Root, CAName]),
- ok = filelib:ensure_dir(CARoot),
- file:make_dir(CARoot),
- create_dirs(CARoot, ["certs", "crl", "newcerts", "private"]),
- create_rnd(Root, filename:join([CAName, "private"])),
- create_files(CARoot, [{"serial", "01\n"},
- {"crlnumber", "01"},
- {"index.txt", ""},
- {"ca.cnf", Cnf}]).
-
-create_req(Root, CnfFile, KeyFile, ReqFile, C = #config{ecc_certs = true}) ->
- Cmd = [C#config.openssl_cmd, " ecparam"
- " -out ", KeyFile,
- " -name secp521r1 ",
- %" -name sect283k1 ",
- " -genkey "],
- Env = [{"ROOTDIR", filename:absname(Root)}],
- cmd(Cmd, Env),
- Cmd2 = [C#config.openssl_cmd, " req"
- " -new ",
- " -key ", KeyFile,
- " -outform PEM ",
- " -out ", ReqFile,
- " -config ", CnfFile],
- cmd(Cmd2, Env);
- %fix_key_file(KeyFile).
-create_req(Root, CnfFile, KeyFile, ReqFile, C) ->
- Cmd = [C#config.openssl_cmd, " req"
- " -new"
- " -config ", CnfFile,
- " -outform PEM ",
- " -keyout ", KeyFile,
- " -out ", ReqFile],
- Env = [{"ROOTDIR", filename:absname(Root)}],
- cmd(Cmd, Env).
- %fix_key_file(KeyFile).
-
-
-sign_req(Root, CA, CertType, ReqFile, CertFile, C) ->
- CACnfFile = filename:join([Root, CA, "ca.cnf"]),
- Cmd = [C#config.openssl_cmd, " ca"
- " -batch"
- " -notext"
- " -config ", CACnfFile,
- " -extensions ", CertType,
- " -in ", ReqFile,
- " -out ", CertFile],
- Env = [{"ROOTDIR", filename:absname(Root)}],
- cmd(Cmd, Env).
-
-%%
-%% Misc
-%%
-
-create_dirs(Root, Dirs) ->
- lists:foreach(fun(Dir) ->
- file:make_dir(filename:join([Root, Dir])) end,
- Dirs).
-
-create_files(Root, NameContents) ->
- lists:foreach(
- fun({Name, Contents}) ->
- file:write_file(filename:join([Root, Name]), Contents) end,
- NameContents).
-
-create_rnd(FromDir, ToDir) ->
- From = filename:join([FromDir, "RAND"]),
- To = filename:join([ToDir, "RAND"]),
- file:copy(From, To).
-
-remove_rnd(Dir) ->
- File = filename:join([Dir, "RAND"]),
- file:delete(File).
-
-cmd(Cmd, Env) ->
- FCmd = lists:flatten(Cmd),
- Port = open_port({spawn, FCmd}, [stream, eof, exit_status, stderr_to_stdout,
- {env, Env}]),
- eval_cmd(Port, FCmd).
-
-eval_cmd(Port, Cmd) ->
- receive
- {Port, {data, _}} ->
- eval_cmd(Port, Cmd);
- {Port, eof} ->
- ok
- end,
- receive
- {Port, {exit_status, 0}} ->
- ok;
- {Port, {exit_status, Status}} ->
- exit({eval_cmd, Cmd, Status})
- after 0 ->
- ok
- end.
-
-%%
-%% Contents of configuration files
-%%
-
-req_cnf(C) ->
- ["# Purpose: Configuration for requests (end users and CAs)."
- "\n"
- "ROOTDIR = $ENV::ROOTDIR\n"
- "\n"
-
- "[req]\n"
- "input_password = secret\n"
- "output_password = secret\n"
- "default_bits = ", integer_to_list(C#config.default_bits), "\n"
- "RANDFILE = $ROOTDIR/RAND\n"
- "encrypt_key = no\n"
- "default_md = md5\n"
- "#string_mask = pkix\n"
- "x509_extensions = ca_ext\n"
- "prompt = no\n"
- "distinguished_name= name\n"
- "\n"
-
- "[name]\n"
- "commonName = ", C#config.commonName, "\n"
- "organizationalUnitName = ", C#config.organizationalUnitName, "\n"
- "organizationName = ", C#config.organizationName, "\n"
- "localityName = ", C#config.localityName, "\n"
- "countryName = ", C#config.countryName, "\n"
- "emailAddress = ", C#config.emailAddress, "\n"
- "\n"
-
- "[ca_ext]\n"
- "basicConstraints = critical, CA:true\n"
- "keyUsage = cRLSign, keyCertSign\n"
- "subjectKeyIdentifier = hash\n"
- "subjectAltName = email:copy\n"].
-
-ca_cnf(C = #config{issuing_distribution_point = true}) ->
- ["# Purpose: Configuration for CAs.\n"
- "\n"
- "ROOTDIR = $ENV::ROOTDIR\n"
- "default_ca = ca\n"
- "\n"
-
- "[ca]\n"
- "dir = $ROOTDIR/", C#config.commonName, "\n"
- "certs = $dir/certs\n"
- "crl_dir = $dir/crl\n"
- "database = $dir/index.txt\n"
- "new_certs_dir = $dir/newcerts\n"
- "certificate = $dir/cert.pem\n"
- "serial = $dir/serial\n"
- "crl = $dir/crl.pem\n",
- ["crlnumber = $dir/crlnumber\n" || C#config.v2_crls],
- "private_key = $dir/private/key.pem\n"
- "RANDFILE = $dir/private/RAND\n"
- "\n"
- "x509_extensions = user_cert\n",
- ["crl_extensions = crl_ext\n" || C#config.v2_crls],
- "unique_subject = no\n"
- "default_days = 3600\n"
- "default_md = md5\n"
- "preserve = no\n"
- "policy = policy_match\n"
- "\n"
-
- "[policy_match]\n"
- "commonName = supplied\n"
- "organizationalUnitName = optional\n"
- "organizationName = match\n"
- "countryName = match\n"
- "localityName = match\n"
- "emailAddress = supplied\n"
- "\n"
-
- "[crl_ext]\n"
- "authorityKeyIdentifier=keyid:always,issuer:always\n",
- ["issuingDistributionPoint=critical, @idpsec\n" || C#config.issuing_distribution_point],
-
- "[idpsec]\n"
- "fullname=URI:http://localhost:8000/",C#config.commonName,"/crl.pem\n"
-
- "[user_cert]\n"
- "basicConstraints = CA:false\n"
- "keyUsage = nonRepudiation, digitalSignature, keyEncipherment\n"
- "subjectKeyIdentifier = hash\n"
- "authorityKeyIdentifier = keyid,issuer:always\n"
- "subjectAltName = email:copy\n"
- "issuerAltName = issuer:copy\n"
- "crlDistributionPoints=@crl_section\n"
-
- "[crl_section]\n"
- %% intentionally invalid
- "URI.1=http://localhost/",C#config.commonName,"/crl.pem\n"
- "URI.2=http://localhost:",integer_to_list(C#config.crl_port),"/",C#config.commonName,"/crl.pem\n"
- "\n"
-
- "[user_cert_digital_signature_only]\n"
- "basicConstraints = CA:false\n"
- "keyUsage = digitalSignature\n"
- "subjectKeyIdentifier = hash\n"
- "authorityKeyIdentifier = keyid,issuer:always\n"
- "subjectAltName = email:copy\n"
- "issuerAltName = issuer:copy\n"
- "\n"
-
- "[ca_cert]\n"
- "basicConstraints = critical,CA:true\n"
- "keyUsage = cRLSign, keyCertSign\n"
- "subjectKeyIdentifier = hash\n"
- "authorityKeyIdentifier = keyid:always,issuer:always\n"
- "subjectAltName = email:copy\n"
- "issuerAltName = issuer:copy\n"
- "crlDistributionPoints=@crl_section\n"
- ];
-
-ca_cnf(C = #config{issuing_distribution_point = false}) ->
- ["# Purpose: Configuration for CAs.\n"
- "\n"
- "ROOTDIR = $ENV::ROOTDIR\n"
- "default_ca = ca\n"
- "\n"
-
- "[ca]\n"
- "dir = $ROOTDIR/", C#config.commonName, "\n"
- "certs = $dir/certs\n"
- "crl_dir = $dir/crl\n"
- "database = $dir/index.txt\n"
- "new_certs_dir = $dir/newcerts\n"
- "certificate = $dir/cert.pem\n"
- "serial = $dir/serial\n"
- "crl = $dir/crl.pem\n",
- ["crlnumber = $dir/crlnumber\n" || C#config.v2_crls],
- "private_key = $dir/private/key.pem\n"
- "RANDFILE = $dir/private/RAND\n"
- "\n"
- "x509_extensions = user_cert\n",
- ["crl_extensions = crl_ext\n" || C#config.v2_crls],
- "unique_subject = no\n"
- "default_days = 3600\n"
- "default_md = md5\n"
- "preserve = no\n"
- "policy = policy_match\n"
- "\n"
-
- "[policy_match]\n"
- "commonName = supplied\n"
- "organizationalUnitName = optional\n"
- "organizationName = match\n"
- "countryName = match\n"
- "localityName = match\n"
- "emailAddress = supplied\n"
- "\n"
-
- "[crl_ext]\n"
- "authorityKeyIdentifier=keyid:always,issuer:always\n",
- %["issuingDistributionPoint=critical, @idpsec\n" || C#config.issuing_distribution_point],
-
- %"[idpsec]\n"
- %"fullname=URI:http://localhost:8000/",C#config.commonName,"/crl.pem\n"
-
- "[user_cert]\n"
- "basicConstraints = CA:false\n"
- "keyUsage = nonRepudiation, digitalSignature, keyEncipherment\n"
- "subjectKeyIdentifier = hash\n"
- "authorityKeyIdentifier = keyid,issuer:always\n"
- "subjectAltName = email:copy\n"
- "issuerAltName = issuer:copy\n"
- %"crlDistributionPoints=@crl_section\n"
-
- %%"[crl_section]\n"
- %% intentionally invalid
- %%"URI.1=http://localhost/",C#config.commonName,"/crl.pem\n"
- %%"URI.2=http://localhost:",integer_to_list(C#config.crl_port),"/",C#config.commonName,"/crl.pem\n"
- %%"\n"
-
- "[user_cert_digital_signature_only]\n"
- "basicConstraints = CA:false\n"
- "keyUsage = digitalSignature\n"
- "subjectKeyIdentifier = hash\n"
- "authorityKeyIdentifier = keyid,issuer:always\n"
- "subjectAltName = email:copy\n"
- "issuerAltName = issuer:copy\n"
- "\n"
-
- "[ca_cert]\n"
- "basicConstraints = critical,CA:true\n"
- "keyUsage = cRLSign, keyCertSign\n"
- "subjectKeyIdentifier = hash\n"
- "authorityKeyIdentifier = keyid:always,issuer:always\n"
- "subjectAltName = email:copy\n"
- "issuerAltName = issuer:copy\n"
- %"crlDistributionPoints=@crl_section\n"
- ].
--
2.51.0