From 80b8fdde48ad538efc8311a48674883d776977a3 Mon Sep 17 00:00:00 2001 From: dcorbacho Date: Mon, 8 Mar 2021 22:59:22 +0100 Subject: [PATCH] Update to ranch 2.0 (cherry picked from commit 61f7b2a7237eb359f215d63d8aa2276d978663c6) --- deps/rabbit/src/rabbit_connection_sup.erl | 6 +- .../src/rabbit_mqtt_connection_sup.erl | 4 +- .../src/rabbit_stomp_client_sup.erl | 4 +- .../rabbitmq-components.mk | 363 ++++++++++++++++++ .../rabbitmq-components.mk | 363 ++++++++++++++++++ .../src/rabbit_web_dispatch_sup.erl | 2 +- .../src/rabbit_web_mqtt_app.erl | 3 +- .../src/rabbit_web_mqtt_connection_sup.erl | 9 +- .../src/rabbit_web_mqtt_handler.erl | 103 +++-- .../src/rabbit_web_mqtt_middleware.erl | 4 +- .../src/rabbit_web_mqtt_stream_handler.erl | 41 ++ .../src/rabbit_web_stomp_connection_sup.erl | 10 +- .../src/rabbit_web_stomp_handler.erl | 37 +- .../src/rabbit_web_stomp_listener.erl | 3 +- .../src/rabbit_web_stomp_middleware.erl | 4 +- .../src/rabbit_web_stomp_stream_handler.erl | 41 ++ 16 files changed, 921 insertions(+), 76 deletions(-) create mode 100644 deps/rabbitmq_stream_management/rabbitmq-components.mk create mode 100644 deps/rabbitmq_stream_prometheus/rabbitmq-components.mk create mode 100644 deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_stream_handler.erl create mode 100644 deps/rabbitmq_web_stomp/src/rabbit_web_stomp_stream_handler.erl diff --git a/deps/rabbit/src/rabbit_connection_sup.erl b/deps/rabbit/src/rabbit_connection_sup.erl index b74723e2d4ee..173015d7c41e 100644 --- a/deps/rabbit/src/rabbit_connection_sup.erl +++ b/deps/rabbit/src/rabbit_connection_sup.erl @@ -19,7 +19,7 @@ -behaviour(supervisor2). -behaviour(ranch_protocol). --export([start_link/4, reader/1]). +-export([start_link/3, reader/1]). -export([init/1]). @@ -27,10 +27,10 @@ %%---------------------------------------------------------------------------- --spec start_link(any(), rabbit_net:socket(), module(), any()) -> +-spec start_link(any(), module(), any()) -> {'ok', pid(), pid()}. -start_link(Ref, _Sock, _Transport, _Opts) -> +start_link(Ref, _Transport, _Opts) -> {ok, SupPid} = supervisor2:start_link(?MODULE, []), %% We need to get channels in the hierarchy here so they get shut %% down after the reader, so the reader gets a chance to terminate diff --git a/deps/rabbitmq_mqtt/src/rabbit_mqtt_connection_sup.erl b/deps/rabbitmq_mqtt/src/rabbit_mqtt_connection_sup.erl index f59679b7b422..20412a1a0c4e 100644 --- a/deps/rabbitmq_mqtt/src/rabbit_mqtt_connection_sup.erl +++ b/deps/rabbitmq_mqtt/src/rabbit_mqtt_connection_sup.erl @@ -12,13 +12,13 @@ -include_lib("rabbit_common/include/rabbit.hrl"). --export([start_link/4, start_keepalive_link/0]). +-export([start_link/3, start_keepalive_link/0]). -export([init/1]). %%---------------------------------------------------------------------------- -start_link(Ref, _Sock, _Transport, []) -> +start_link(Ref, _Transport, []) -> {ok, SupPid} = supervisor2:start_link(?MODULE, []), {ok, KeepaliveSup} = supervisor2:start_child( SupPid, diff --git a/deps/rabbitmq_stomp/src/rabbit_stomp_client_sup.erl b/deps/rabbitmq_stomp/src/rabbit_stomp_client_sup.erl index 099a7b51782b..6548351a4f5e 100644 --- a/deps/rabbitmq_stomp/src/rabbit_stomp_client_sup.erl +++ b/deps/rabbitmq_stomp/src/rabbit_stomp_client_sup.erl @@ -11,9 +11,9 @@ -include_lib("rabbit_common/include/rabbit.hrl"). --export([start_link/4, init/1]). +-export([start_link/3, init/1]). -start_link(Ref, _Sock, _Transport, Configuration) -> +start_link(Ref, _Transport, Configuration) -> {ok, SupPid} = supervisor2:start_link(?MODULE, []), {ok, HelperPid} = supervisor2:start_child(SupPid, diff --git a/deps/rabbitmq_stream_management/rabbitmq-components.mk b/deps/rabbitmq_stream_management/rabbitmq-components.mk new file mode 100644 index 000000000000..bc4f0fa58f41 --- /dev/null +++ b/deps/rabbitmq_stream_management/rabbitmq-components.mk @@ -0,0 +1,363 @@ +ifeq ($(.DEFAULT_GOAL),) +# Define default goal to `all` because this file defines some targets +# before the inclusion of erlang.mk leading to the wrong target becoming +# the default. +.DEFAULT_GOAL = all +endif + +# PROJECT_VERSION defaults to: +# 1. the version exported by rabbitmq-server-release; +# 2. the version stored in `git-revisions.txt`, if it exists; +# 3. a version based on git-describe(1), if it is a Git clone; +# 4. 0.0.0 + +PROJECT_VERSION := $(RABBITMQ_VERSION) + +ifeq ($(PROJECT_VERSION),) +PROJECT_VERSION := $(shell \ +if test -f git-revisions.txt; then \ + head -n1 git-revisions.txt | \ + awk '{print $$$(words $(PROJECT_DESCRIPTION) version);}'; \ +else \ + (git describe --dirty --abbrev=7 --tags --always --first-parent \ + 2>/dev/null || echo rabbitmq_v0_0_0) | \ + sed -e 's/^rabbitmq_v//' -e 's/^v//' -e 's/_/./g' -e 's/-/+/' \ + -e 's/-/./g'; \ +fi) +endif + +# -------------------------------------------------------------------- +# RabbitMQ components. +# -------------------------------------------------------------------- + +# For RabbitMQ repositories, we want to checkout branches which match +# the parent project. For instance, if the parent project is on a +# release tag, dependencies must be on the same release tag. If the +# parent project is on a topic branch, dependencies must be on the same +# topic branch or fallback to `stable` or `master` whichever was the +# base of the topic branch. + +dep_amqp_client = git_rmq rabbitmq-erlang-client $(current_rmq_ref) $(base_rmq_ref) master +dep_amqp10_client = git_rmq rabbitmq-amqp1.0-client $(current_rmq_ref) $(base_rmq_ref) master +dep_amqp10_common = git_rmq rabbitmq-amqp1.0-common $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbit = git_rmq rabbitmq-server $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbit_common = git_rmq rabbitmq-common $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_amqp1_0 = git_rmq rabbitmq-amqp1.0 $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_auth_backend_amqp = git_rmq rabbitmq-auth-backend-amqp $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_auth_backend_cache = git_rmq rabbitmq-auth-backend-cache $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_auth_backend_http = git_rmq rabbitmq-auth-backend-http $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_auth_backend_ldap = git_rmq rabbitmq-auth-backend-ldap $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_auth_backend_oauth2 = git_rmq rabbitmq-auth-backend-oauth2 $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_auth_mechanism_ssl = git_rmq rabbitmq-auth-mechanism-ssl $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_aws = git_rmq rabbitmq-aws $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_boot_steps_visualiser = git_rmq rabbitmq-boot-steps-visualiser $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_cli = git_rmq rabbitmq-cli $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_codegen = git_rmq rabbitmq-codegen $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_consistent_hash_exchange = git_rmq rabbitmq-consistent-hash-exchange $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_ct_client_helpers = git_rmq rabbitmq-ct-client-helpers $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_ct_helpers = git_rmq rabbitmq-ct-helpers $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_delayed_message_exchange = git_rmq rabbitmq-delayed-message-exchange $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_dotnet_client = git_rmq rabbitmq-dotnet-client $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_event_exchange = git_rmq rabbitmq-event-exchange $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_federation = git_rmq rabbitmq-federation $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_federation_management = git_rmq rabbitmq-federation-management $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_java_client = git_rmq rabbitmq-java-client $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_jms_client = git_rmq rabbitmq-jms-client $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_jms_cts = git_rmq rabbitmq-jms-cts $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_jms_topic_exchange = git_rmq rabbitmq-jms-topic-exchange $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_lvc_exchange = git_rmq rabbitmq-lvc-exchange $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_management = git_rmq rabbitmq-management $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_management_agent = git_rmq rabbitmq-management-agent $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_management_exchange = git_rmq rabbitmq-management-exchange $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_management_themes = git_rmq rabbitmq-management-themes $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_message_timestamp = git_rmq rabbitmq-message-timestamp $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_metronome = git_rmq rabbitmq-metronome $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_mqtt = git_rmq rabbitmq-mqtt $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_objc_client = git_rmq rabbitmq-objc-client $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_peer_discovery_aws = git_rmq rabbitmq-peer-discovery-aws $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_peer_discovery_common = git_rmq rabbitmq-peer-discovery-common $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_peer_discovery_consul = git_rmq rabbitmq-peer-discovery-consul $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_peer_discovery_etcd = git_rmq rabbitmq-peer-discovery-etcd $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_peer_discovery_k8s = git_rmq rabbitmq-peer-discovery-k8s $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_prometheus = git_rmq rabbitmq-prometheus $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_random_exchange = git_rmq rabbitmq-random-exchange $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_recent_history_exchange = git_rmq rabbitmq-recent-history-exchange $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_routing_node_stamp = git_rmq rabbitmq-routing-node-stamp $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_rtopic_exchange = git_rmq rabbitmq-rtopic-exchange $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_server_release = git_rmq rabbitmq-server-release $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_sharding = git_rmq rabbitmq-sharding $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_stream_prometheus = git_rmq rabbitmq-stream-prometheus $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_trust_store = git_rmq rabbitmq-trust-store $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_test = git_rmq rabbitmq-test $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_web_dispatch = git_rmq rabbitmq-web-dispatch $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_web_stomp = git_rmq rabbitmq-web-stomp $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_web_stomp_examples = git_rmq rabbitmq-web-stomp-examples $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_web_mqtt = git_rmq rabbitmq-web-mqtt $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_web_mqtt_examples = git_rmq rabbitmq-web-mqtt-examples $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_website = git_rmq rabbitmq-website $(current_rmq_ref) $(base_rmq_ref) live master +dep_toke = git_rmq toke $(current_rmq_ref) $(base_rmq_ref) master + +dep_rabbitmq_public_umbrella = git_rmq rabbitmq-public-umbrella $(current_rmq_ref) $(base_rmq_ref) master + +# Third-party dependencies version pinning. +# +# We do that in this file, which is copied in all projects, to ensure +# all projects use the same versions. It avoids conflicts and makes it +# possible to work with rabbitmq-public-umbrella. + +dep_accept = hex 0.3.5 +dep_cowboy = hex 2.8.0 +dep_cowlib = hex 2.9.1 +dep_jsx = hex 2.11.0 +dep_lager = hex 3.9.1 +dep_prometheus = git https://github.com/deadtrickster/prometheus.erl.git master +dep_ra = git https://github.com/rabbitmq/ra.git master +dep_ranch = hex 2.0.0 +dep_recon = hex 2.5.1 +dep_observer_cli = hex 1.6.1 +dep_stdout_formatter = hex 0.2.4 +dep_sysmon_handler = hex 1.3.0 + +RABBITMQ_COMPONENTS = amqp_client \ + amqp10_common \ + amqp10_client \ + rabbit \ + rabbit_common \ + rabbitmq_amqp1_0 \ + rabbitmq_auth_backend_amqp \ + rabbitmq_auth_backend_cache \ + rabbitmq_auth_backend_http \ + rabbitmq_auth_backend_ldap \ + rabbitmq_auth_backend_oauth2 \ + rabbitmq_auth_mechanism_ssl \ + rabbitmq_aws \ + rabbitmq_boot_steps_visualiser \ + rabbitmq_cli \ + rabbitmq_codegen \ + rabbitmq_consistent_hash_exchange \ + rabbitmq_ct_client_helpers \ + rabbitmq_ct_helpers \ + rabbitmq_delayed_message_exchange \ + rabbitmq_dotnet_client \ + rabbitmq_event_exchange \ + rabbitmq_federation \ + rabbitmq_federation_management \ + rabbitmq_java_client \ + rabbitmq_jms_client \ + rabbitmq_jms_cts \ + rabbitmq_jms_topic_exchange \ + rabbitmq_lvc_exchange \ + rabbitmq_management \ + rabbitmq_management_agent \ + rabbitmq_management_exchange \ + rabbitmq_management_themes \ + rabbitmq_message_timestamp \ + rabbitmq_metronome \ + rabbitmq_mqtt \ + rabbitmq_objc_client \ + rabbitmq_peer_discovery_aws \ + rabbitmq_peer_discovery_common \ + rabbitmq_peer_discovery_consul \ + rabbitmq_peer_discovery_etcd \ + rabbitmq_peer_discovery_k8s \ + rabbitmq_prometheus \ + rabbitmq_random_exchange \ + rabbitmq_recent_history_exchange \ + rabbitmq_routing_node_stamp \ + rabbitmq_rtopic_exchange \ + rabbitmq_server_release \ + rabbitmq_sharding \ + rabbitmq_shovel \ + rabbitmq_shovel_management \ + rabbitmq_stomp \ + rabbitmq_stream \ + rabbitmq_stream_management \ + rabbitmq_stream_prometheus \ + rabbitmq_toke \ + rabbitmq_top \ + rabbitmq_tracing \ + rabbitmq_trust_store \ + rabbitmq_web_dispatch \ + rabbitmq_web_mqtt \ + rabbitmq_web_mqtt_examples \ + rabbitmq_web_stomp \ + rabbitmq_web_stomp_examples \ + rabbitmq_website + +# Erlang.mk does not rebuild dependencies by default, once they were +# compiled once, except for those listed in the `$(FORCE_REBUILD)` +# variable. +# +# We want all RabbitMQ components to always be rebuilt: this eases +# the work on several components at the same time. + +FORCE_REBUILD = $(RABBITMQ_COMPONENTS) + +# Several components have a custom erlang.mk/build.config, mainly +# to disable eunit. Therefore, we can't use the top-level project's +# erlang.mk copy. +NO_AUTOPATCH += $(RABBITMQ_COMPONENTS) + +ifeq ($(origin current_rmq_ref),undefined) +ifneq ($(wildcard .git),) +current_rmq_ref := $(shell (\ + ref=$$(LANG=C git branch --list | awk '/^\* \(.*detached / {ref=$$0; sub(/.*detached [^ ]+ /, "", ref); sub(/\)$$/, "", ref); print ref; exit;} /^\* / {ref=$$0; sub(/^\* /, "", ref); print ref; exit}');\ + if test "$$(git rev-parse --short HEAD)" != "$$ref"; then echo "$$ref"; fi)) +else +current_rmq_ref := master +endif +endif +export current_rmq_ref + +ifeq ($(origin base_rmq_ref),undefined) +ifneq ($(wildcard .git),) +possible_base_rmq_ref := master +ifeq ($(possible_base_rmq_ref),$(current_rmq_ref)) +base_rmq_ref := $(current_rmq_ref) +else +base_rmq_ref := $(shell \ + (git rev-parse --verify -q master >/dev/null && \ + git rev-parse --verify -q $(possible_base_rmq_ref) >/dev/null && \ + git merge-base --is-ancestor $$(git merge-base master HEAD) $(possible_base_rmq_ref) && \ + echo $(possible_base_rmq_ref)) || \ + echo master) +endif +else +base_rmq_ref := master +endif +endif +export base_rmq_ref + +# Repository URL selection. +# +# First, we infer other components' location from the current project +# repository URL, if it's a Git repository: +# - We take the "origin" remote URL as the base +# - The current project name and repository name is replaced by the +# target's properties: +# eg. rabbitmq-common is replaced by rabbitmq-codegen +# eg. rabbit_common is replaced by rabbitmq_codegen +# +# If cloning from this computed location fails, we fallback to RabbitMQ +# upstream which is GitHub. + +# Macro to transform eg. "rabbit_common" to "rabbitmq-common". +rmq_cmp_repo_name = $(word 2,$(dep_$(1))) + +# Upstream URL for the current project. +RABBITMQ_COMPONENT_REPO_NAME := $(call rmq_cmp_repo_name,$(PROJECT)) +RABBITMQ_UPSTREAM_FETCH_URL ?= https://github.com/rabbitmq/$(RABBITMQ_COMPONENT_REPO_NAME).git +RABBITMQ_UPSTREAM_PUSH_URL ?= git@github.com:rabbitmq/$(RABBITMQ_COMPONENT_REPO_NAME).git + +# Current URL for the current project. If this is not a Git clone, +# default to the upstream Git repository. +ifneq ($(wildcard .git),) +git_origin_fetch_url := $(shell git config remote.origin.url) +git_origin_push_url := $(shell git config remote.origin.pushurl || git config remote.origin.url) +RABBITMQ_CURRENT_FETCH_URL ?= $(git_origin_fetch_url) +RABBITMQ_CURRENT_PUSH_URL ?= $(git_origin_push_url) +else +RABBITMQ_CURRENT_FETCH_URL ?= $(RABBITMQ_UPSTREAM_FETCH_URL) +RABBITMQ_CURRENT_PUSH_URL ?= $(RABBITMQ_UPSTREAM_PUSH_URL) +endif + +# Macro to replace the following pattern: +# 1. /foo.git -> /bar.git +# 2. /foo -> /bar +# 3. /foo/ -> /bar/ +subst_repo_name = $(patsubst %/$(1)/%,%/$(2)/%,$(patsubst %/$(1),%/$(2),$(patsubst %/$(1).git,%/$(2).git,$(3)))) + +# Macro to replace both the project's name (eg. "rabbit_common") and +# repository name (eg. "rabbitmq-common") by the target's equivalent. +# +# This macro is kept on one line because we don't want whitespaces in +# the returned value, as it's used in $(dep_fetch_git_rmq) in a shell +# single-quoted string. +dep_rmq_repo = $(if $(dep_$(2)),$(call subst_repo_name,$(PROJECT),$(2),$(call subst_repo_name,$(RABBITMQ_COMPONENT_REPO_NAME),$(call rmq_cmp_repo_name,$(2)),$(1))),$(pkg_$(1)_repo)) + +dep_rmq_commits = $(if $(dep_$(1)), \ + $(wordlist 3,$(words $(dep_$(1))),$(dep_$(1))), \ + $(pkg_$(1)_commit)) + +define dep_fetch_git_rmq + fetch_url1='$(call dep_rmq_repo,$(RABBITMQ_CURRENT_FETCH_URL),$(1))'; \ + fetch_url2='$(call dep_rmq_repo,$(RABBITMQ_UPSTREAM_FETCH_URL),$(1))'; \ + if test "$$$$fetch_url1" != '$(RABBITMQ_CURRENT_FETCH_URL)' && \ + git clone -q -n -- "$$$$fetch_url1" $(DEPS_DIR)/$(call dep_name,$(1)); then \ + fetch_url="$$$$fetch_url1"; \ + push_url='$(call dep_rmq_repo,$(RABBITMQ_CURRENT_PUSH_URL),$(1))'; \ + elif git clone -q -n -- "$$$$fetch_url2" $(DEPS_DIR)/$(call dep_name,$(1)); then \ + fetch_url="$$$$fetch_url2"; \ + push_url='$(call dep_rmq_repo,$(RABBITMQ_UPSTREAM_PUSH_URL),$(1))'; \ + fi; \ + cd $(DEPS_DIR)/$(call dep_name,$(1)) && ( \ + $(foreach ref,$(call dep_rmq_commits,$(1)), \ + git checkout -q $(ref) >/dev/null 2>&1 || \ + ) \ + (echo "error: no valid pathspec among: $(call dep_rmq_commits,$(1))" \ + 1>&2 && false) ) && \ + (test "$$$$fetch_url" = "$$$$push_url" || \ + git remote set-url --push origin "$$$$push_url") +endef + +# -------------------------------------------------------------------- +# Component distribution. +# -------------------------------------------------------------------- + +list-dist-deps:: + @: + +prepare-dist:: + @: + +# -------------------------------------------------------------------- +# Umbrella-specific settings. +# -------------------------------------------------------------------- + +# If the top-level project is a RabbitMQ component, we override +# $(DEPS_DIR) for this project to point to the top-level's one. +# +# We also verify that the guessed DEPS_DIR is actually named `deps`, +# to rule out any situation where it is a coincidence that we found a +# `rabbitmq-components.mk` up upper directories. + +possible_deps_dir_1 = $(abspath ..) +possible_deps_dir_2 = $(abspath ../../..) + +ifeq ($(notdir $(possible_deps_dir_1)),deps) +ifneq ($(wildcard $(possible_deps_dir_1)/../rabbitmq-components.mk),) +deps_dir_overriden = 1 +DEPS_DIR ?= $(possible_deps_dir_1) +DISABLE_DISTCLEAN = 1 +endif +endif + +ifeq ($(deps_dir_overriden),) +ifeq ($(notdir $(possible_deps_dir_2)),deps) +ifneq ($(wildcard $(possible_deps_dir_2)/../rabbitmq-components.mk),) +deps_dir_overriden = 1 +DEPS_DIR ?= $(possible_deps_dir_2) +DISABLE_DISTCLEAN = 1 +endif +endif +endif + +ifneq ($(wildcard UMBRELLA.md),) +DISABLE_DISTCLEAN = 1 +endif + +# We disable `make distclean` so $(DEPS_DIR) is not accidentally removed. + +ifeq ($(DISABLE_DISTCLEAN),1) +ifneq ($(filter distclean distclean-deps,$(MAKECMDGOALS)),) +SKIP_DEPS = 1 +endif +endif diff --git a/deps/rabbitmq_stream_prometheus/rabbitmq-components.mk b/deps/rabbitmq_stream_prometheus/rabbitmq-components.mk new file mode 100644 index 000000000000..bc4f0fa58f41 --- /dev/null +++ b/deps/rabbitmq_stream_prometheus/rabbitmq-components.mk @@ -0,0 +1,363 @@ +ifeq ($(.DEFAULT_GOAL),) +# Define default goal to `all` because this file defines some targets +# before the inclusion of erlang.mk leading to the wrong target becoming +# the default. +.DEFAULT_GOAL = all +endif + +# PROJECT_VERSION defaults to: +# 1. the version exported by rabbitmq-server-release; +# 2. the version stored in `git-revisions.txt`, if it exists; +# 3. a version based on git-describe(1), if it is a Git clone; +# 4. 0.0.0 + +PROJECT_VERSION := $(RABBITMQ_VERSION) + +ifeq ($(PROJECT_VERSION),) +PROJECT_VERSION := $(shell \ +if test -f git-revisions.txt; then \ + head -n1 git-revisions.txt | \ + awk '{print $$$(words $(PROJECT_DESCRIPTION) version);}'; \ +else \ + (git describe --dirty --abbrev=7 --tags --always --first-parent \ + 2>/dev/null || echo rabbitmq_v0_0_0) | \ + sed -e 's/^rabbitmq_v//' -e 's/^v//' -e 's/_/./g' -e 's/-/+/' \ + -e 's/-/./g'; \ +fi) +endif + +# -------------------------------------------------------------------- +# RabbitMQ components. +# -------------------------------------------------------------------- + +# For RabbitMQ repositories, we want to checkout branches which match +# the parent project. For instance, if the parent project is on a +# release tag, dependencies must be on the same release tag. If the +# parent project is on a topic branch, dependencies must be on the same +# topic branch or fallback to `stable` or `master` whichever was the +# base of the topic branch. + +dep_amqp_client = git_rmq rabbitmq-erlang-client $(current_rmq_ref) $(base_rmq_ref) master +dep_amqp10_client = git_rmq rabbitmq-amqp1.0-client $(current_rmq_ref) $(base_rmq_ref) master +dep_amqp10_common = git_rmq rabbitmq-amqp1.0-common $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbit = git_rmq rabbitmq-server $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbit_common = git_rmq rabbitmq-common $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_amqp1_0 = git_rmq rabbitmq-amqp1.0 $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_auth_backend_amqp = git_rmq rabbitmq-auth-backend-amqp $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_auth_backend_cache = git_rmq rabbitmq-auth-backend-cache $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_auth_backend_http = git_rmq rabbitmq-auth-backend-http $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_auth_backend_ldap = git_rmq rabbitmq-auth-backend-ldap $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_auth_backend_oauth2 = git_rmq rabbitmq-auth-backend-oauth2 $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_auth_mechanism_ssl = git_rmq rabbitmq-auth-mechanism-ssl $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_aws = git_rmq rabbitmq-aws $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_boot_steps_visualiser = git_rmq rabbitmq-boot-steps-visualiser $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_cli = git_rmq rabbitmq-cli $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_codegen = git_rmq rabbitmq-codegen $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_consistent_hash_exchange = git_rmq rabbitmq-consistent-hash-exchange $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_ct_client_helpers = git_rmq rabbitmq-ct-client-helpers $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_ct_helpers = git_rmq rabbitmq-ct-helpers $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_delayed_message_exchange = git_rmq rabbitmq-delayed-message-exchange $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_dotnet_client = git_rmq rabbitmq-dotnet-client $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_event_exchange = git_rmq rabbitmq-event-exchange $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_federation = git_rmq rabbitmq-federation $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_federation_management = git_rmq rabbitmq-federation-management $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_java_client = git_rmq rabbitmq-java-client $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_jms_client = git_rmq rabbitmq-jms-client $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_jms_cts = git_rmq rabbitmq-jms-cts $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_jms_topic_exchange = git_rmq rabbitmq-jms-topic-exchange $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_lvc_exchange = git_rmq rabbitmq-lvc-exchange $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_management = git_rmq rabbitmq-management $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_management_agent = git_rmq rabbitmq-management-agent $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_management_exchange = git_rmq rabbitmq-management-exchange $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_management_themes = git_rmq rabbitmq-management-themes $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_message_timestamp = git_rmq rabbitmq-message-timestamp $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_metronome = git_rmq rabbitmq-metronome $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_mqtt = git_rmq rabbitmq-mqtt $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_objc_client = git_rmq rabbitmq-objc-client $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_peer_discovery_aws = git_rmq rabbitmq-peer-discovery-aws $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_peer_discovery_common = git_rmq rabbitmq-peer-discovery-common $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_peer_discovery_consul = git_rmq rabbitmq-peer-discovery-consul $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_peer_discovery_etcd = git_rmq rabbitmq-peer-discovery-etcd $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_peer_discovery_k8s = git_rmq rabbitmq-peer-discovery-k8s $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_prometheus = git_rmq rabbitmq-prometheus $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_random_exchange = git_rmq rabbitmq-random-exchange $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_recent_history_exchange = git_rmq rabbitmq-recent-history-exchange $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_routing_node_stamp = git_rmq rabbitmq-routing-node-stamp $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_rtopic_exchange = git_rmq rabbitmq-rtopic-exchange $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_server_release = git_rmq rabbitmq-server-release $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_sharding = git_rmq rabbitmq-sharding $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_stream_prometheus = git_rmq rabbitmq-stream-prometheus $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_trust_store = git_rmq rabbitmq-trust-store $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_test = git_rmq rabbitmq-test $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_web_dispatch = git_rmq rabbitmq-web-dispatch $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_web_stomp = git_rmq rabbitmq-web-stomp $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_web_stomp_examples = git_rmq rabbitmq-web-stomp-examples $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_web_mqtt = git_rmq rabbitmq-web-mqtt $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_web_mqtt_examples = git_rmq rabbitmq-web-mqtt-examples $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_website = git_rmq rabbitmq-website $(current_rmq_ref) $(base_rmq_ref) live master +dep_toke = git_rmq toke $(current_rmq_ref) $(base_rmq_ref) master + +dep_rabbitmq_public_umbrella = git_rmq rabbitmq-public-umbrella $(current_rmq_ref) $(base_rmq_ref) master + +# Third-party dependencies version pinning. +# +# We do that in this file, which is copied in all projects, to ensure +# all projects use the same versions. It avoids conflicts and makes it +# possible to work with rabbitmq-public-umbrella. + +dep_accept = hex 0.3.5 +dep_cowboy = hex 2.8.0 +dep_cowlib = hex 2.9.1 +dep_jsx = hex 2.11.0 +dep_lager = hex 3.9.1 +dep_prometheus = git https://github.com/deadtrickster/prometheus.erl.git master +dep_ra = git https://github.com/rabbitmq/ra.git master +dep_ranch = hex 2.0.0 +dep_recon = hex 2.5.1 +dep_observer_cli = hex 1.6.1 +dep_stdout_formatter = hex 0.2.4 +dep_sysmon_handler = hex 1.3.0 + +RABBITMQ_COMPONENTS = amqp_client \ + amqp10_common \ + amqp10_client \ + rabbit \ + rabbit_common \ + rabbitmq_amqp1_0 \ + rabbitmq_auth_backend_amqp \ + rabbitmq_auth_backend_cache \ + rabbitmq_auth_backend_http \ + rabbitmq_auth_backend_ldap \ + rabbitmq_auth_backend_oauth2 \ + rabbitmq_auth_mechanism_ssl \ + rabbitmq_aws \ + rabbitmq_boot_steps_visualiser \ + rabbitmq_cli \ + rabbitmq_codegen \ + rabbitmq_consistent_hash_exchange \ + rabbitmq_ct_client_helpers \ + rabbitmq_ct_helpers \ + rabbitmq_delayed_message_exchange \ + rabbitmq_dotnet_client \ + rabbitmq_event_exchange \ + rabbitmq_federation \ + rabbitmq_federation_management \ + rabbitmq_java_client \ + rabbitmq_jms_client \ + rabbitmq_jms_cts \ + rabbitmq_jms_topic_exchange \ + rabbitmq_lvc_exchange \ + rabbitmq_management \ + rabbitmq_management_agent \ + rabbitmq_management_exchange \ + rabbitmq_management_themes \ + rabbitmq_message_timestamp \ + rabbitmq_metronome \ + rabbitmq_mqtt \ + rabbitmq_objc_client \ + rabbitmq_peer_discovery_aws \ + rabbitmq_peer_discovery_common \ + rabbitmq_peer_discovery_consul \ + rabbitmq_peer_discovery_etcd \ + rabbitmq_peer_discovery_k8s \ + rabbitmq_prometheus \ + rabbitmq_random_exchange \ + rabbitmq_recent_history_exchange \ + rabbitmq_routing_node_stamp \ + rabbitmq_rtopic_exchange \ + rabbitmq_server_release \ + rabbitmq_sharding \ + rabbitmq_shovel \ + rabbitmq_shovel_management \ + rabbitmq_stomp \ + rabbitmq_stream \ + rabbitmq_stream_management \ + rabbitmq_stream_prometheus \ + rabbitmq_toke \ + rabbitmq_top \ + rabbitmq_tracing \ + rabbitmq_trust_store \ + rabbitmq_web_dispatch \ + rabbitmq_web_mqtt \ + rabbitmq_web_mqtt_examples \ + rabbitmq_web_stomp \ + rabbitmq_web_stomp_examples \ + rabbitmq_website + +# Erlang.mk does not rebuild dependencies by default, once they were +# compiled once, except for those listed in the `$(FORCE_REBUILD)` +# variable. +# +# We want all RabbitMQ components to always be rebuilt: this eases +# the work on several components at the same time. + +FORCE_REBUILD = $(RABBITMQ_COMPONENTS) + +# Several components have a custom erlang.mk/build.config, mainly +# to disable eunit. Therefore, we can't use the top-level project's +# erlang.mk copy. +NO_AUTOPATCH += $(RABBITMQ_COMPONENTS) + +ifeq ($(origin current_rmq_ref),undefined) +ifneq ($(wildcard .git),) +current_rmq_ref := $(shell (\ + ref=$$(LANG=C git branch --list | awk '/^\* \(.*detached / {ref=$$0; sub(/.*detached [^ ]+ /, "", ref); sub(/\)$$/, "", ref); print ref; exit;} /^\* / {ref=$$0; sub(/^\* /, "", ref); print ref; exit}');\ + if test "$$(git rev-parse --short HEAD)" != "$$ref"; then echo "$$ref"; fi)) +else +current_rmq_ref := master +endif +endif +export current_rmq_ref + +ifeq ($(origin base_rmq_ref),undefined) +ifneq ($(wildcard .git),) +possible_base_rmq_ref := master +ifeq ($(possible_base_rmq_ref),$(current_rmq_ref)) +base_rmq_ref := $(current_rmq_ref) +else +base_rmq_ref := $(shell \ + (git rev-parse --verify -q master >/dev/null && \ + git rev-parse --verify -q $(possible_base_rmq_ref) >/dev/null && \ + git merge-base --is-ancestor $$(git merge-base master HEAD) $(possible_base_rmq_ref) && \ + echo $(possible_base_rmq_ref)) || \ + echo master) +endif +else +base_rmq_ref := master +endif +endif +export base_rmq_ref + +# Repository URL selection. +# +# First, we infer other components' location from the current project +# repository URL, if it's a Git repository: +# - We take the "origin" remote URL as the base +# - The current project name and repository name is replaced by the +# target's properties: +# eg. rabbitmq-common is replaced by rabbitmq-codegen +# eg. rabbit_common is replaced by rabbitmq_codegen +# +# If cloning from this computed location fails, we fallback to RabbitMQ +# upstream which is GitHub. + +# Macro to transform eg. "rabbit_common" to "rabbitmq-common". +rmq_cmp_repo_name = $(word 2,$(dep_$(1))) + +# Upstream URL for the current project. +RABBITMQ_COMPONENT_REPO_NAME := $(call rmq_cmp_repo_name,$(PROJECT)) +RABBITMQ_UPSTREAM_FETCH_URL ?= https://github.com/rabbitmq/$(RABBITMQ_COMPONENT_REPO_NAME).git +RABBITMQ_UPSTREAM_PUSH_URL ?= git@github.com:rabbitmq/$(RABBITMQ_COMPONENT_REPO_NAME).git + +# Current URL for the current project. If this is not a Git clone, +# default to the upstream Git repository. +ifneq ($(wildcard .git),) +git_origin_fetch_url := $(shell git config remote.origin.url) +git_origin_push_url := $(shell git config remote.origin.pushurl || git config remote.origin.url) +RABBITMQ_CURRENT_FETCH_URL ?= $(git_origin_fetch_url) +RABBITMQ_CURRENT_PUSH_URL ?= $(git_origin_push_url) +else +RABBITMQ_CURRENT_FETCH_URL ?= $(RABBITMQ_UPSTREAM_FETCH_URL) +RABBITMQ_CURRENT_PUSH_URL ?= $(RABBITMQ_UPSTREAM_PUSH_URL) +endif + +# Macro to replace the following pattern: +# 1. /foo.git -> /bar.git +# 2. /foo -> /bar +# 3. /foo/ -> /bar/ +subst_repo_name = $(patsubst %/$(1)/%,%/$(2)/%,$(patsubst %/$(1),%/$(2),$(patsubst %/$(1).git,%/$(2).git,$(3)))) + +# Macro to replace both the project's name (eg. "rabbit_common") and +# repository name (eg. "rabbitmq-common") by the target's equivalent. +# +# This macro is kept on one line because we don't want whitespaces in +# the returned value, as it's used in $(dep_fetch_git_rmq) in a shell +# single-quoted string. +dep_rmq_repo = $(if $(dep_$(2)),$(call subst_repo_name,$(PROJECT),$(2),$(call subst_repo_name,$(RABBITMQ_COMPONENT_REPO_NAME),$(call rmq_cmp_repo_name,$(2)),$(1))),$(pkg_$(1)_repo)) + +dep_rmq_commits = $(if $(dep_$(1)), \ + $(wordlist 3,$(words $(dep_$(1))),$(dep_$(1))), \ + $(pkg_$(1)_commit)) + +define dep_fetch_git_rmq + fetch_url1='$(call dep_rmq_repo,$(RABBITMQ_CURRENT_FETCH_URL),$(1))'; \ + fetch_url2='$(call dep_rmq_repo,$(RABBITMQ_UPSTREAM_FETCH_URL),$(1))'; \ + if test "$$$$fetch_url1" != '$(RABBITMQ_CURRENT_FETCH_URL)' && \ + git clone -q -n -- "$$$$fetch_url1" $(DEPS_DIR)/$(call dep_name,$(1)); then \ + fetch_url="$$$$fetch_url1"; \ + push_url='$(call dep_rmq_repo,$(RABBITMQ_CURRENT_PUSH_URL),$(1))'; \ + elif git clone -q -n -- "$$$$fetch_url2" $(DEPS_DIR)/$(call dep_name,$(1)); then \ + fetch_url="$$$$fetch_url2"; \ + push_url='$(call dep_rmq_repo,$(RABBITMQ_UPSTREAM_PUSH_URL),$(1))'; \ + fi; \ + cd $(DEPS_DIR)/$(call dep_name,$(1)) && ( \ + $(foreach ref,$(call dep_rmq_commits,$(1)), \ + git checkout -q $(ref) >/dev/null 2>&1 || \ + ) \ + (echo "error: no valid pathspec among: $(call dep_rmq_commits,$(1))" \ + 1>&2 && false) ) && \ + (test "$$$$fetch_url" = "$$$$push_url" || \ + git remote set-url --push origin "$$$$push_url") +endef + +# -------------------------------------------------------------------- +# Component distribution. +# -------------------------------------------------------------------- + +list-dist-deps:: + @: + +prepare-dist:: + @: + +# -------------------------------------------------------------------- +# Umbrella-specific settings. +# -------------------------------------------------------------------- + +# If the top-level project is a RabbitMQ component, we override +# $(DEPS_DIR) for this project to point to the top-level's one. +# +# We also verify that the guessed DEPS_DIR is actually named `deps`, +# to rule out any situation where it is a coincidence that we found a +# `rabbitmq-components.mk` up upper directories. + +possible_deps_dir_1 = $(abspath ..) +possible_deps_dir_2 = $(abspath ../../..) + +ifeq ($(notdir $(possible_deps_dir_1)),deps) +ifneq ($(wildcard $(possible_deps_dir_1)/../rabbitmq-components.mk),) +deps_dir_overriden = 1 +DEPS_DIR ?= $(possible_deps_dir_1) +DISABLE_DISTCLEAN = 1 +endif +endif + +ifeq ($(deps_dir_overriden),) +ifeq ($(notdir $(possible_deps_dir_2)),deps) +ifneq ($(wildcard $(possible_deps_dir_2)/../rabbitmq-components.mk),) +deps_dir_overriden = 1 +DEPS_DIR ?= $(possible_deps_dir_2) +DISABLE_DISTCLEAN = 1 +endif +endif +endif + +ifneq ($(wildcard UMBRELLA.md),) +DISABLE_DISTCLEAN = 1 +endif + +# We disable `make distclean` so $(DEPS_DIR) is not accidentally removed. + +ifeq ($(DISABLE_DISTCLEAN),1) +ifneq ($(filter distclean distclean-deps,$(MAKECMDGOALS)),) +SKIP_DEPS = 1 +endif +endif diff --git a/deps/rabbitmq_web_dispatch/src/rabbit_web_dispatch_sup.erl b/deps/rabbitmq_web_dispatch/src/rabbit_web_dispatch_sup.erl index e93153fcc52f..01af6bd1bbec 100644 --- a/deps/rabbitmq_web_dispatch/src/rabbit_web_dispatch_sup.erl +++ b/deps/rabbitmq_web_dispatch/src/rabbit_web_dispatch_sup.erl @@ -39,7 +39,7 @@ ensure_listener(Listener) -> [rabbit_cowboy_middleware, cowboy_router, cowboy_handler], stream_handlers => StreamHandlers}, ProtoOptsMap), - Child = ranch:child_spec(rabbit_networking:ranch_ref(Listener), 100, + Child = ranch:child_spec(rabbit_networking:ranch_ref(Listener), Transport, TransportOpts, cowboy_clear, CowboyOptsMap), case supervisor:start_child(?SUP, Child) of diff --git a/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_app.erl b/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_app.erl index e7b0d965cd60..1c9f0d79f903 100644 --- a/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_app.erl +++ b/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_app.erl @@ -86,7 +86,8 @@ mqtt_init() -> ]}]), CowboyOpts = CowboyOpts0#{env => #{dispatch => Routes}, middlewares => [cowboy_router, rabbit_web_mqtt_middleware, cowboy_handler], - proxy_header => get_env(proxy_protocol, false)}, + proxy_header => get_env(proxy_protocol, false), + stream_handlers => [rabbit_web_mqtt_stream_handler, cowboy_stream_h]}, case get_env(tcp_config, []) of [] -> ok; TCPConf0 -> start_tcp_listener(TCPConf0, CowboyOpts) diff --git a/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_connection_sup.erl b/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_connection_sup.erl index 3400b9beb481..53ed3b9a09a1 100644 --- a/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_connection_sup.erl +++ b/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_connection_sup.erl @@ -12,13 +12,13 @@ -include_lib("rabbit_common/include/rabbit.hrl"). --export([start_link/4, start_keepalive_link/0]). +-export([start_link/3, start_keepalive_link/0]). -export([init/1]). %%---------------------------------------------------------------------------- -start_link(Ref, Sock, Transport, CowboyOpts0) -> +start_link(Ref, Transport, CowboyOpts0) -> {ok, SupPid} = supervisor2:start_link(?MODULE, []), {ok, KeepaliveSup} = supervisor2:start_child( SupPid, @@ -31,8 +31,7 @@ start_link(Ref, Sock, Transport, CowboyOpts0) -> %% then have the middleware rabbit_web_mqtt_middleware place it %% in the initial handler state. Env = maps:get(env, CowboyOpts0), - CowboyOpts = CowboyOpts0#{env => Env#{keepalive_sup => KeepaliveSup, - socket => Sock}}, + CowboyOpts = CowboyOpts0#{env => Env#{keepalive_sup => KeepaliveSup}}, Protocol = case Transport of ranch_tcp -> cowboy_clear; ranch_ssl -> cowboy_tls @@ -40,7 +39,7 @@ start_link(Ref, Sock, Transport, CowboyOpts0) -> {ok, ReaderPid} = supervisor2:start_child( SupPid, {Protocol, - {Protocol, start_link, [Ref, Sock, Transport, CowboyOpts]}, + {Protocol, start_link, [Ref, Transport, CowboyOpts]}, intrinsic, ?WORKER_WAIT, worker, [Protocol]}), {ok, SupPid, ReaderPid}. diff --git a/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_handler.erl b/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_handler.erl index 2f77745d5354..7396ce1d3a44 100644 --- a/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_handler.erl +++ b/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_handler.erl @@ -7,6 +7,7 @@ -module(rabbit_web_mqtt_handler). -behaviour(cowboy_websocket). +-behaviour(cowboy_sub_protocol). -export([ init/2, @@ -17,6 +18,11 @@ ]). -export([close_connection/2]). +%% cowboy_sub_protocol +-export([upgrade/4, + upgrade/5, + takeover/7]). + -include_lib("amqp_client/include/amqp_client.hrl"). -record(state, { @@ -33,55 +39,70 @@ connection }). +%% cowboy_sub_protcol +upgrade(Req, Env, Handler, HandlerState) -> + upgrade(Req, Env, Handler, HandlerState, #{}). + +upgrade(Req, Env, Handler, HandlerState, Opts) -> + cowboy_websocket:upgrade(Req, Env, Handler, HandlerState, Opts). + +takeover(Parent, Ref, Socket, Transport, Opts, Buffer, {Handler, HandlerState}) -> + Sock = case HandlerState#state.socket of + undefined -> + Socket; + ProxyInfo -> + {rabbit_proxy_socket, Socket, ProxyInfo} + end, + cowboy_websocket:takeover(Parent, Ref, Socket, Transport, Opts, Buffer, + {Handler, HandlerState#state{socket = Sock}}). + +%% cowboy_websocket init(Req, Opts) -> {PeerAddr, _PeerPort} = maps:get(peer, Req), {_, KeepaliveSup} = lists:keyfind(keepalive_sup, 1, Opts), - {_, Sock0} = lists:keyfind(socket, 1, Opts), - Sock = case maps:get(proxy_header, Req, undefined) of - undefined -> - Sock0; - ProxyInfo -> - {rabbit_proxy_socket, Sock0, ProxyInfo} - end, + SockInfo = maps:get(proxy_header, Req, undefined), + WsOpts0 = proplists:get_value(ws_opts, Opts, #{}), + WsOpts = maps:merge(#{compress => true}, WsOpts0), + Req2 = case cowboy_req:header(<<"sec-websocket-protocol">>, Req) of + undefined -> Req; + SecWsProtocol -> + cowboy_req:set_resp_header(<<"sec-websocket-protocol">>, SecWsProtocol, Req) + end, + {?MODULE, Req2, #state{ + keepalive = {none, none}, + keepalive_sup = KeepaliveSup, + parse_state = rabbit_mqtt_frame:initial_state(), + state = running, + conserve_resources = false, + socket = SockInfo, + peername = PeerAddr + }, WsOpts}. + +websocket_init(State0 = #state{socket = Sock, peername = PeerAddr}) -> case rabbit_net:connection_string(Sock, inbound) of {ok, ConnStr} -> - Req2 = case cowboy_req:header(<<"sec-websocket-protocol">>, Req) of - undefined -> Req; - SecWsProtocol -> - cowboy_req:set_resp_header(<<"sec-websocket-protocol">>, SecWsProtocol, Req) - end, - WsOpts0 = proplists:get_value(ws_opts, Opts, #{}), - WsOpts = maps:merge(#{compress => true}, WsOpts0), - {cowboy_websocket, Req2, #state{ - conn_name = ConnStr, - keepalive = {none, none}, - keepalive_sup = KeepaliveSup, - parse_state = rabbit_mqtt_frame:initial_state(), - state = running, - conserve_resources = false, - socket = Sock, - peername = PeerAddr - }, WsOpts}; + State = State0#state{ + conn_name = ConnStr, + socket = Sock + }, + rabbit_log_connection:info("accepting Web MQTT connection ~p (~s)~n", [self(), ConnStr]), + AdapterInfo = amqp_connection:socket_adapter_info(Sock, {'Web MQTT', "N/A"}), + RealSocket = rabbit_net:unwrap_socket(Sock), + ProcessorState = rabbit_mqtt_processor:initial_state(Sock, + rabbit_mqtt_reader:ssl_login_name(RealSocket), + AdapterInfo, + fun send_reply/2, + PeerAddr), + process_flag(trap_exit, true), + {ok, + rabbit_event:init_stats_timer( + State#state{proc_state = ProcessorState}, + #state.stats_timer), + hibernate}; _ -> - {stop, Req} + {stop, State0} end. -websocket_init(State = #state{conn_name = ConnStr, socket = Sock, peername = PeerAddr}) -> - rabbit_log_connection:info("accepting Web MQTT connection ~p (~s)~n", [self(), ConnStr]), - AdapterInfo = amqp_connection:socket_adapter_info(Sock, {'Web MQTT', "N/A"}), - RealSocket = rabbit_net:unwrap_socket(Sock), - ProcessorState = rabbit_mqtt_processor:initial_state(Sock, - rabbit_mqtt_reader:ssl_login_name(RealSocket), - AdapterInfo, - fun send_reply/2, - PeerAddr), - process_flag(trap_exit, true), - {ok, - rabbit_event:init_stats_timer( - State#state{proc_state = ProcessorState}, - #state.stats_timer), - hibernate}. - -spec close_connection(pid(), string()) -> 'ok'. close_connection(Pid, Reason) -> rabbit_log_connection:info("Web MQTT: will terminate connection process ~p, reason: ~s", diff --git a/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_middleware.erl b/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_middleware.erl index fe8c8e737e11..41bdabd1e045 100644 --- a/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_middleware.erl +++ b/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_middleware.erl @@ -12,11 +12,9 @@ execute(Req, Env) -> #{keepalive_sup := KeepaliveSup} = Env, - Sock = maps:get(socket, Env), case maps:get(handler_opts, Env, undefined) of undefined -> {ok, Req, Env}; Opts when is_list(Opts) -> - {ok, Req, Env#{handler_opts => [{keepalive_sup, KeepaliveSup}, - {socket, Sock} + {ok, Req, Env#{handler_opts => [{keepalive_sup, KeepaliveSup} |Opts]}} end. diff --git a/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_stream_handler.erl b/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_stream_handler.erl new file mode 100644 index 000000000000..f7ffd57a4724 --- /dev/null +++ b/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_stream_handler.erl @@ -0,0 +1,41 @@ +%% This Source Code Form is subject to the terms of the Mozilla Public +%% License, v. 2.0. If a copy of the MPL was not distributed with this +%% file, You can obtain one at https://mozilla.org/MPL/2.0/. +%% +%% Copyright (c) 2007-2021 VMware, Inc. or its affiliates. All rights reserved. +%% +-module(rabbit_web_mqtt_stream_handler). + +-behavior(cowboy_stream). + +-export([init/3]). +-export([data/4]). +-export([info/3]). +-export([terminate/3]). +-export([early_error/5]). + + +-record(state, {next}). + +init(StreamID, Req, Opts) -> + {Commands, Next} = cowboy_stream:init(StreamID, Req, Opts), + {Commands, #state{next = Next}}. + +data(StreamID, IsFin, Data, State = #state{next = Next0}) -> + {Commands, Next} = cowboy_stream:data(StreamID, IsFin, Data, Next0), + {Commands, State#state{next = Next}}. + +info(StreamID, {switch_protocol, Headers, _, InitialState}, State) -> + do_info(StreamID, {switch_protocol, Headers, rabbit_web_mqtt_handler, InitialState}, State); +info(StreamID, Info, State) -> + do_info(StreamID, Info, State). + +do_info(StreamID, Info, State = #state{next = Next0}) -> + {Commands, Next} = cowboy_stream:info(StreamID, Info, Next0), + {Commands, State#state{next = Next}}. + +terminate(StreamID, Reason, State = #state{next = Next}) -> + cowboy_stream:terminate(StreamID, Reason, Next). + +early_error(StreamID, Reason, PartialReq, Resp, Opts) -> + cowboy_stream:early_error(StreamID, Reason, PartialReq, Resp, Opts). diff --git a/deps/rabbitmq_web_stomp/src/rabbit_web_stomp_connection_sup.erl b/deps/rabbitmq_web_stomp/src/rabbit_web_stomp_connection_sup.erl index 66f84ea48a83..771653fa84d8 100644 --- a/deps/rabbitmq_web_stomp/src/rabbit_web_stomp_connection_sup.erl +++ b/deps/rabbitmq_web_stomp/src/rabbit_web_stomp_connection_sup.erl @@ -12,12 +12,12 @@ -include_lib("rabbit_common/include/rabbit.hrl"). --export([start_link/4, start_keepalive_link/0]). +-export([start_link/3, start_keepalive_link/0]). -export([init/1]). %%---------------------------------------------------------------------------- -start_link(Ref, Sock, Transport, CowboyOpts0) -> +start_link(Ref, Transport, CowboyOpts0) -> {ok, SupPid} = supervisor2:start_link(?MODULE, []), {ok, KeepaliveSup} = supervisor2:start_child( SupPid, @@ -29,8 +29,8 @@ start_link(Ref, Sock, Transport, CowboyOpts0) -> %% then have the middleware rabbit_web_mqtt_middleware place it %% in the initial handler state. Env = maps:get(env, CowboyOpts0), - CowboyOpts = CowboyOpts0#{env => Env#{keepalive_sup => KeepaliveSup, - socket => Sock}}, + CowboyOpts = CowboyOpts0#{env => Env#{keepalive_sup => KeepaliveSup}, + stream_handlers => [rabbit_web_stomp_stream_handler, cowboy_stream_h]}, Protocol = case Transport of ranch_tcp -> cowboy_clear; ranch_ssl -> cowboy_tls @@ -38,7 +38,7 @@ start_link(Ref, Sock, Transport, CowboyOpts0) -> {ok, ReaderPid} = supervisor2:start_child( SupPid, {Protocol, - {Protocol, start_link, [Ref, Sock, Transport, CowboyOpts]}, + {Protocol, start_link, [Ref, Transport, CowboyOpts]}, intrinsic, ?WORKER_WAIT, worker, [Protocol]}), {ok, SupPid, ReaderPid}. diff --git a/deps/rabbitmq_web_stomp/src/rabbit_web_stomp_handler.erl b/deps/rabbitmq_web_stomp/src/rabbit_web_stomp_handler.erl index 958fcda6e5e9..74b2e881f2cf 100644 --- a/deps/rabbitmq_web_stomp/src/rabbit_web_stomp_handler.erl +++ b/deps/rabbitmq_web_stomp/src/rabbit_web_stomp_handler.erl @@ -7,6 +7,7 @@ -module(rabbit_web_stomp_handler). -behaviour(cowboy_websocket). +-behaviour(cowboy_sub_protocol). -include_lib("rabbitmq_stomp/include/rabbit_stomp.hrl"). -include_lib("rabbitmq_stomp/include/rabbit_stomp_frame.hrl"). @@ -22,6 +23,11 @@ ]). -export([close_connection/2]). +%% cowboy_sub_protocol +-export([upgrade/4, + upgrade/5, + takeover/7]). + -record(state, { frame_type, heartbeat_mode, @@ -38,17 +44,30 @@ connection }). +%% cowboy_sub_protcol +upgrade(Req, Env, Handler, HandlerState) -> + upgrade(Req, Env, Handler, HandlerState, #{}). + +upgrade(Req, Env, Handler, HandlerState, Opts) -> + cowboy_websocket:upgrade(Req, Env, Handler, HandlerState, Opts). + +takeover(Parent, Ref, Socket, Transport, Opts, Buffer, {Handler, HandlerState}) -> + Sock = case HandlerState#state.socket of + undefined -> + Socket; + ProxyInfo -> + {rabbit_proxy_socket, Socket, ProxyInfo} + end, + Env0 = maps:get(env, Opts, #{}), + Env = Env0#{socket => Sock}, + cowboy_websocket:takeover(Parent, Ref, Socket, Transport, maps:put(env, Env, Opts), Buffer, + {Handler, HandlerState#state{socket = Sock}}). + %% Websocket. init(Req0, Opts) -> {PeerAddr, _PeerPort} = maps:get(peer, Req0), {_, KeepaliveSup} = lists:keyfind(keepalive_sup, 1, Opts), - {_, Sock0} = lists:keyfind(socket, 1, Opts), - Sock = case maps:get(proxy_header, Req0, undefined) of - undefined -> - Sock0; - ProxyInfo -> - {rabbit_proxy_socket, Sock0, ProxyInfo} - end, + SockInfo = maps:get(proxy_header, Req0, undefined), Req = case cowboy_req:parse_header(<<"sec-websocket-protocol">>, Req0) of undefined -> Req0; Protocols -> @@ -61,14 +80,14 @@ init(Req0, Opts) -> end, WsOpts0 = proplists:get_value(ws_opts, Opts, #{}), WsOpts = maps:merge(#{compress => true}, WsOpts0), - {cowboy_websocket, Req, #state{ + {?MODULE, Req, #state{ frame_type = proplists:get_value(type, Opts, text), heartbeat_sup = KeepaliveSup, heartbeat = {none, none}, heartbeat_mode = heartbeat, state = running, conserve_resources = false, - socket = Sock, + socket = SockInfo, peername = PeerAddr, auth_hd = cowboy_req:header(<<"authorization">>, Req) }, WsOpts}. diff --git a/deps/rabbitmq_web_stomp/src/rabbit_web_stomp_listener.erl b/deps/rabbitmq_web_stomp/src/rabbit_web_stomp_listener.erl index 8c4fb7e9903f..fc35204372df 100644 --- a/deps/rabbitmq_web_stomp/src/rabbit_web_stomp_listener.erl +++ b/deps/rabbitmq_web_stomp/src/rabbit_web_stomp_listener.erl @@ -32,7 +32,8 @@ init() -> WsFrame = get_env(ws_frame, text), CowboyOpts0 = maps:from_list(get_env(cowboy_opts, [])), - CowboyOpts = CowboyOpts0#{proxy_header => get_env(proxy_protocol, false)}, + CowboyOpts = CowboyOpts0#{proxy_header => get_env(proxy_protocol, false), + stream_handlers => [rabbit_web_stomp_stream_handler, cowboy_stream_h]}, CowboyWsOpts = maps:from_list(get_env(cowboy_ws_opts, [])), VhostRoutes = [ diff --git a/deps/rabbitmq_web_stomp/src/rabbit_web_stomp_middleware.erl b/deps/rabbitmq_web_stomp/src/rabbit_web_stomp_middleware.erl index f1f22f6f04a6..356d4110da3d 100644 --- a/deps/rabbitmq_web_stomp/src/rabbit_web_stomp_middleware.erl +++ b/deps/rabbitmq_web_stomp/src/rabbit_web_stomp_middleware.erl @@ -12,11 +12,9 @@ execute(Req, Env) -> #{keepalive_sup := KeepaliveSup} = Env, - Sock = maps:get(socket, Env), case maps:get(handler_opts, Env, undefined) of undefined -> {ok, Req, Env}; Opts when is_list(Opts) -> - {ok, Req, Env#{handler_opts => [{keepalive_sup, KeepaliveSup}, - {socket, Sock} + {ok, Req, Env#{handler_opts => [{keepalive_sup, KeepaliveSup} |Opts]}} end. diff --git a/deps/rabbitmq_web_stomp/src/rabbit_web_stomp_stream_handler.erl b/deps/rabbitmq_web_stomp/src/rabbit_web_stomp_stream_handler.erl new file mode 100644 index 000000000000..a4d950e77e15 --- /dev/null +++ b/deps/rabbitmq_web_stomp/src/rabbit_web_stomp_stream_handler.erl @@ -0,0 +1,41 @@ +%% This Source Code Form is subject to the terms of the Mozilla Public +%% License, v. 2.0. If a copy of the MPL was not distributed with this +%% file, You can obtain one at https://mozilla.org/MPL/2.0/. +%% +%% Copyright (c) 2007-2021 VMware, Inc. or its affiliates. All rights reserved. +%% +-module(rabbit_web_stomp_stream_handler). + +-behavior(cowboy_stream). + +-export([init/3]). +-export([data/4]). +-export([info/3]). +-export([terminate/3]). +-export([early_error/5]). + + +-record(state, {next}). + +init(StreamID, Req, Opts) -> + {Commands, Next} = cowboy_stream:init(StreamID, Req, Opts), + {Commands, #state{next = Next}}. + +data(StreamID, IsFin, Data, State = #state{next = Next0}) -> + {Commands, Next} = cowboy_stream:data(StreamID, IsFin, Data, Next0), + {Commands, State#state{next = Next}}. + +info(StreamID, {switch_protocol, Headers, _, InitialState}, State) -> + do_info(StreamID, {switch_protocol, Headers, rabbit_web_stomp_handler, InitialState}, State); +info(StreamID, Info, State) -> + do_info(StreamID, Info, State). + +do_info(StreamID, Info, State = #state{next = Next0}) -> + {Commands, Next} = cowboy_stream:info(StreamID, Info, Next0), + {Commands, State#state{next = Next}}. + +terminate(StreamID, Reason, State = #state{next = Next}) -> + cowboy_stream:terminate(StreamID, Reason, Next). + +early_error(StreamID, Reason, PartialReq, Resp, Opts) -> + cowboy_stream:early_error(StreamID, Reason, PartialReq, Resp, Opts).