aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS11
-rw-r--r--Makefile3
-rwxr-xr-xall.sh4
-rw-r--r--erlang.mk773
-rw-r--r--examples/tcp_echo/Makefile3
-rw-r--r--examples/tcp_reverse/Makefile3
-rw-r--r--guide/introduction.md5
-rw-r--r--guide/protocols.md4
-rw-r--r--manual/ranch_app.md2
-rw-r--r--src/ranch.app.src4
-rw-r--r--src/ranch.erl2
-rw-r--r--src/ranch_acceptor.erl2
-rw-r--r--src/ranch_acceptors_sup.erl2
-rw-r--r--src/ranch_app.erl2
-rw-r--r--src/ranch_conns_sup.erl2
-rw-r--r--src/ranch_listener_sup.erl2
-rw-r--r--src/ranch_protocol.erl2
-rw-r--r--src/ranch_server.erl2
-rw-r--r--src/ranch_ssl.erl2
-rw-r--r--src/ranch_sup.erl2
-rw-r--r--src/ranch_tcp.erl2
-rw-r--r--src/ranch_transport.erl2
22 files changed, 636 insertions, 200 deletions
diff --git a/AUTHORS b/AUTHORS
index 93fda6a..b5ce283 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,14 +1,19 @@
Ranch is available thanks to the work of:
Loïc Hoguin
-Andrew Majorov
James Fish
+Andrew Majorov
+Ransom Richardson
Fred Hebert
+Geoff Cant
+Klaus Trainer
+josh rotenberg
0x00F6
+Alexander Zhuravlev
Ali Sabil
Andrew Thompson
-Geoff Cant
-Ransom Richardson
+Slava Yurin
+Xiao Jia
The Ranch code was initially part of Cowboy. Before it was
split into a separate project, the following people worked
diff --git a/Makefile b/Makefile
index 0535bd5..c29e45f 100644
--- a/Makefile
+++ b/Makefile
@@ -5,12 +5,11 @@ PROJECT = ranch
# Dependencies.
TEST_DEPS = ct_helper
-dep_ct_helper = https://github.com/extend/ct_helper.git master
+dep_ct_helper = git https://github.com/extend/ct_helper.git master
# Options.
COMPILE_FIRST = ranch_transport
-CT_SUITES = acceptor sendfile shutdown
PLT_APPS = crypto public_key ssl
# Standard targets.
diff --git a/all.sh b/all.sh
index 8f6032b..d463ada 100755
--- a/all.sh
+++ b/all.sh
@@ -1,9 +1,9 @@
#!/bin/sh
KERL_INSTALL_PATH=~/erlang
-KERL_RELEASES="r15b01 r15b02 r15b03 r16b r16b01 r16b02 r16b03 maint master"
+KERL_RELEASES="r15b01 r15b02 r15b03 r16b r16b01 r16b02 r16b03-1 17.0 17.1.2"
-make build-tests
+make build-ct-suites
for rel in $KERL_RELEASES
do
diff --git a/erlang.mk b/erlang.mk
index 1e0a05e..b04703b 100644
--- a/erlang.mk
+++ b/erlang.mk
@@ -1,4 +1,4 @@
-# Copyright (c) 2013, Loïc Hoguin <[email protected]>
+# Copyright (c) 2013-2014, Loïc Hoguin <[email protected]>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@@ -12,108 +12,199 @@
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-# Project.
+.PHONY: all deps app rel docs tests clean distclean help
+
+ERLANG_MK_VERSION = 1
+
+# Core configuration.
PROJECT ?= $(notdir $(CURDIR))
+PROJECT := $(strip $(PROJECT))
-# Packages database file.
+# Verbosity.
-PKG_FILE ?= $(CURDIR)/.erlang.mk.packages.v1
-export PKG_FILE
+V ?= 0
-PKG_FILE_URL ?= https://raw.github.com/extend/erlang.mk/master/packages.v1.tsv
+gen_verbose_0 = @echo " GEN " $@;
+gen_verbose = $(gen_verbose_$(V))
-define get_pkg_file
- wget --no-check-certificate -O $(PKG_FILE) $(PKG_FILE_URL) || rm $(PKG_FILE)
+# Core targets.
+
+all:: deps app rel
+
+clean::
+ $(gen_verbose) rm -f erl_crash.dump
+
+distclean:: clean
+
+help::
+ @printf "%s\n" \
+ "erlang.mk (version $(ERLANG_MK_VERSION)) is distributed under the terms of the ISC License." \
+ "Copyright (c) 2013-2014 Loïc Hoguin <[email protected]>" \
+ "" \
+ "Usage: [V=1] make [target]" \
+ "" \
+ "Core targets:" \
+ " all Run deps, app and rel targets in that order" \
+ " deps Fetch dependencies (if needed) and compile them" \
+ " app Compile the project" \
+ " rel Build a release for this project, if applicable" \
+ " docs Build the documentation for this project" \
+ " tests Run the tests for this project" \
+ " clean Delete temporary and output files from most targets" \
+ " distclean Delete all temporary and output files" \
+ " help Display this help and exit" \
+ "" \
+ "The target clean only removes files that are commonly removed." \
+ "Dependencies and releases are left untouched." \
+ "" \
+ "Setting V=1 when calling make enables verbose mode."
+
+# Core functions.
+
+define core_http_get
+ wget --no-check-certificate -O $(1) $(2)|| rm $(1)
endef
-# Verbosity and tweaks.
+# Copyright (c) 2013-2014, Loïc Hoguin <[email protected]>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
-V ?= 0
+.PHONY: distclean-deps distclean-pkg pkg-list pkg-search
-appsrc_verbose_0 = @echo " APP " $(PROJECT).app.src;
-appsrc_verbose = $(appsrc_verbose_$(V))
+# Configuration.
-erlc_verbose_0 = @echo " ERLC " $(filter %.erl %.core,$(?F));
-erlc_verbose = $(erlc_verbose_$(V))
+DEPS_DIR ?= $(CURDIR)/deps
+export DEPS_DIR
-xyrl_verbose_0 = @echo " XYRL " $(filter %.xrl %.yrl,$(?F));
-xyrl_verbose = $(xyrl_verbose_$(V))
+REBAR_DEPS_DIR = $(DEPS_DIR)
+export REBAR_DEPS_DIR
-dtl_verbose_0 = @echo " DTL " $(filter %.dtl,$(?F));
-dtl_verbose = $(dtl_verbose_$(V))
+ALL_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(DEPS))
-gen_verbose_0 = @echo " GEN " $@;
-gen_verbose = $(gen_verbose_$(V))
+ifeq ($(filter $(DEPS_DIR),$(subst :, ,$(ERL_LIBS))),)
+ifeq ($(ERL_LIBS),)
+ ERL_LIBS = $(DEPS_DIR)
+else
+ ERL_LIBS := $(ERL_LIBS):$(DEPS_DIR)
+endif
+endif
+export ERL_LIBS
-.PHONY: rel clean-rel all clean-all app clean deps clean-deps \
- docs clean-docs build-tests tests build-plt dialyze
+PKG_FILE2 ?= $(CURDIR)/.erlang.mk.packages.v2
+export PKG_FILE2
-# Release.
+PKG_FILE_URL ?= https://raw.githubusercontent.com/extend/erlang.mk/master/packages.v2.tsv
-RELX_CONFIG ?= $(CURDIR)/relx.config
+# Core targets.
-ifneq ($(wildcard $(RELX_CONFIG)),)
+deps:: $(ALL_DEPS_DIRS)
+ @for dep in $(ALL_DEPS_DIRS) ; do \
+ if [ -f $$dep/GNUmakefile ] || [ -f $$dep/makefile ] || [ -f $$dep/Makefile ] ; then \
+ $(MAKE) -C $$dep ; \
+ else \
+ echo "include $(CURDIR)/erlang.mk" | $(MAKE) -f - -C $$dep ; \
+ fi ; \
+ done
-RELX ?= $(CURDIR)/relx
-export RELX
+distclean:: distclean-deps distclean-pkg
-RELX_URL ?= https://github.com/erlware/relx/releases/download/v0.5.2/relx
-RELX_OPTS ?=
+# Deps related targets.
-define get_relx
- wget -O $(RELX) $(RELX_URL) || rm $(RELX)
- chmod +x $(RELX)
+define dep_fetch
+ if [ "$$$$VS" = "git" ]; then \
+ git clone -n -- $$$$REPO $(DEPS_DIR)/$(1); \
+ cd $(DEPS_DIR)/$(1) && git checkout -q $$$$COMMIT; \
+ else \
+ exit 78; \
+ fi
endef
-rel: clean-rel all $(RELX)
- @$(RELX) -c $(RELX_CONFIG) $(RELX_OPTS)
-
-$(RELX):
- @$(call get_relx)
-
-clean-rel:
- @rm -rf _rel
-
+define dep_target
+$(DEPS_DIR)/$(1):
+ @mkdir -p $(DEPS_DIR)
+ @if [ ! -f $(PKG_FILE2) ]; then $(call core_http_get,$(PKG_FILE2),$(PKG_FILE_URL)); fi
+ifeq (,$(dep_$(1)))
+ DEPPKG=$$$$(awk 'BEGIN { FS = "\t" }; $$$$1 == "$(1)" { print $$$$2 " " $$$$3 " " $$$$4 }' $(PKG_FILE2);) \
+ VS=$$$$(echo $$$$DEPPKG | cut -d " " -f1); \
+ REPO=$$$$(echo $$$$DEPPKG | cut -d " " -f2); \
+ COMMIT=$$$$(echo $$$$DEPPKG | cut -d " " -f3); \
+ $(call dep_fetch,$(1))
+else
+ VS=$(word 1,$(dep_$(1))); \
+ REPO=$(word 2,$(dep_$(1))); \
+ COMMIT=$(word 3,$(dep_$(1))); \
+ $(call dep_fetch,$(1))
endif
+endef
-# Deps directory.
+$(foreach dep,$(DEPS),$(eval $(call dep_target,$(dep))))
-DEPS_DIR ?= $(CURDIR)/deps
-export DEPS_DIR
+distclean-deps:
+ $(gen_verbose) rm -rf $(DEPS_DIR)
-REBAR_DEPS_DIR = $(DEPS_DIR)
-export REBAR_DEPS_DIR
+# Packages related targets.
-ALL_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(DEPS))
-ALL_TEST_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(TEST_DEPS))
+$(PKG_FILE2):
+ $(call core_http_get,$(PKG_FILE2),$(PKG_FILE_URL))
-# Application.
+pkg-list: $(PKG_FILE2)
+ @cat $(PKG_FILE2) | awk 'BEGIN { FS = "\t" }; { print \
+ "Name:\t\t" $$1 "\n" \
+ "Repository:\t" $$3 "\n" \
+ "Website:\t" $$5 "\n" \
+ "Description:\t" $$6 "\n" }'
-ifeq ($(filter $(DEPS_DIR),$(subst :, ,$(ERL_LIBS))),)
-ifeq ($(ERL_LIBS),)
- ERL_LIBS = $(DEPS_DIR)
+ifdef q
+pkg-search: $(PKG_FILE2)
+ @cat $(PKG_FILE2) | grep -i ${q} | awk 'BEGIN { FS = "\t" }; { print \
+ "Name:\t\t" $$1 "\n" \
+ "Repository:\t" $$3 "\n" \
+ "Website:\t" $$5 "\n" \
+ "Description:\t" $$6 "\n" }'
else
- ERL_LIBS := $(ERL_LIBS):$(DEPS_DIR)
-endif
+pkg-search:
+ $(error Usage: make pkg-search q=STRING)
endif
-export ERL_LIBS
+
+distclean-pkg:
+ $(gen_verbose) rm -f $(PKG_FILE2)
+
+help::
+ @printf "%s\n" "" \
+ "Package-related targets:" \
+ " pkg-list List all known packages" \
+ " pkg-search q=STRING Search for STRING in the package index"
+
+# Copyright (c) 2013-2014, Loïc Hoguin <[email protected]>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+.PHONY: clean-app
+
+# Configuration.
ERLC_OPTS ?= -Werror +debug_info +warn_export_all +warn_export_vars \
+warn_shadow_vars +warn_obsolete_guard # +bin_opt_info +warn_missing_spec
COMPILE_FIRST ?=
COMPILE_FIRST_PATHS = $(addprefix src/,$(addsuffix .erl,$(COMPILE_FIRST)))
-all: deps app
+# Verbosity.
+
+appsrc_verbose_0 = @echo " APP " $(PROJECT).app.src;
+appsrc_verbose = $(appsrc_verbose_$(V))
+
+erlc_verbose_0 = @echo " ERLC " $(filter %.erl %.core,$(?F));
+erlc_verbose = $(erlc_verbose_$(V))
-clean-all: clean clean-deps clean-docs
- $(gen_verbose) rm -rf .$(PROJECT).plt $(DEPS_DIR) logs
+xyrl_verbose_0 = @echo " XYRL " $(filter %.xrl %.yrl,$(?F));
+xyrl_verbose = $(xyrl_verbose_$(V))
-app: ebin/$(PROJECT).app
+# Core targets.
+
+app:: ebin/$(PROJECT).app
$(eval MODULES := $(shell find ebin -type f -name \*.beam \
- | sed 's/ebin\///;s/\.beam/,/' | sed '$$s/.$$//'))
+ | sed "s/ebin\//'/;s/\.beam/',/" | sed '$$s/.$$//'))
$(appsrc_verbose) cat src/$(PROJECT).app.src \
- | sed 's/{modules,[[:space:]]*\[\]}/{modules, \[$(MODULES)\]}/' \
+ | sed "s/{modules,[[:space:]]*\[\]}/{modules, \[$(MODULES)\]}/" \
> ebin/$(PROJECT).app
define compile_erl
@@ -127,161 +218,503 @@ define compile_xyrl
@rm ebin/*.erl
endef
-define compile_dtl
- $(dtl_verbose) erl -noshell -pa ebin/ $(DEPS_DIR)/erlydtl/ebin/ -eval ' \
- Compile = fun(F) -> \
- Module = list_to_atom( \
- string:to_lower(filename:basename(F, ".dtl")) ++ "_dtl"), \
- erlydtl_compiler:compile(F, Module, [{out_dir, "ebin/"}]) \
- end, \
- _ = [Compile(F) || F <- string:tokens("$(1)", " ")], \
- init:stop()'
-endef
-
-ebin/$(PROJECT).app: $(shell find src -type f -name \*.erl) \
- $(shell find src -type f -name \*.core) \
- $(shell find src -type f -name \*.xrl) \
- $(shell find src -type f -name \*.yrl) \
- $(shell find templates -type f -name \*.dtl 2>/dev/null)
+ifneq ($(wildcard src/),)
+ebin/$(PROJECT).app::
@mkdir -p ebin/
- $(if $(strip $(filter %.erl %.core,$?)), \
- $(call compile_erl,$(filter %.erl %.core,$?)))
- $(if $(strip $(filter %.xrl %.yrl,$?)), \
- $(call compile_xyrl,$(filter %.xrl %.yrl,$?)))
- $(if $(strip $(filter %.dtl,$?)), \
- $(call compile_dtl,$(filter %.dtl,$?)))
-clean:
- $(gen_verbose) rm -rf ebin/ test/*.beam erl_crash.dump
+ebin/$(PROJECT).app:: $(shell find src -type f -name \*.erl) \
+ $(shell find src -type f -name \*.core)
+ $(if $(strip $?),$(call compile_erl,$?))
-# Dependencies.
+ebin/$(PROJECT).app:: $(shell find src -type f -name \*.xrl) \
+ $(shell find src -type f -name \*.yrl)
+ $(if $(strip $?),$(call compile_xyrl,$?))
+endif
-define get_dep
- @mkdir -p $(DEPS_DIR)
-ifeq (,$(findstring pkg://,$(word 1,$(dep_$(1)))))
- git clone -n -- $(word 1,$(dep_$(1))) $(DEPS_DIR)/$(1)
-else
- @if [ ! -f $(PKG_FILE) ]; then $(call get_pkg_file); fi
- git clone -n -- `awk 'BEGIN { FS = "\t" }; \
- $$$$1 == "$(subst pkg://,,$(word 1,$(dep_$(1))))" { print $$$$2 }' \
- $(PKG_FILE)` $(DEPS_DIR)/$(1)
+clean:: clean-app
+
+# Extra targets.
+
+clean-app:
+ $(gen_verbose) rm -rf ebin/
+
+# Copyright (c) 2014, Loïc Hoguin <[email protected]>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+.PHONY: bootstrap bootstrap-lib bootstrap-rel new list-templates
+
+# Core targets.
+
+help::
+ @printf "%s\n" "" \
+ "Bootstrap targets:" \
+ " bootstrap Generate a skeleton of an OTP application" \
+ " bootstrap-lib Generate a skeleton of an OTP library" \
+ " bootstrap-rel Generate the files needed to build a release" \
+ " new t=TPL n=NAME Generate a module NAME based on the template TPL" \
+ " bootstrap-lib List available templates"
+
+# Bootstrap templates.
+
+bs_appsrc = "{application, $(PROJECT), [" \
+ " {description, \"\"}," \
+ " {vsn, \"0.1.0\"}," \
+ " {modules, []}," \
+ " {registered, []}," \
+ " {applications, [" \
+ " kernel," \
+ " stdlib" \
+ " ]}," \
+ " {mod, {$(PROJECT)_app, []}}," \
+ " {env, []}" \
+ "]}."
+bs_appsrc_lib = "{application, $(PROJECT), [" \
+ " {description, \"\"}," \
+ " {vsn, \"0.1.0\"}," \
+ " {modules, []}," \
+ " {registered, []}," \
+ " {applications, [" \
+ " kernel," \
+ " stdlib" \
+ " ]}" \
+ "]}."
+bs_Makefile = "PROJECT = $(PROJECT)" \
+ "include erlang.mk"
+bs_app = "-module($(PROJECT)_app)." \
+ "-behaviour(application)." \
+ "" \
+ "-export([start/2])." \
+ "-export([stop/1])." \
+ "" \
+ "start(_Type, _Args) ->" \
+ " $(PROJECT)_sup:start_link()." \
+ "" \
+ "stop(_State) ->" \
+ " ok."
+bs_relx_config = "{release, {$(PROJECT)_release, \"1\"}, [$(PROJECT)]}." \
+ "{extended_start_script, true}." \
+ "{sys_config, \"rel/sys.config\"}." \
+ "{vm_args, \"rel/vm.args\"}."
+bs_sys_config = "[" \
+ "]."
+bs_vm_args = "-name $(PROJECT)@127.0.0.1" \
+ "-setcookie $(PROJECT)" \
+ "-heart"
+# Normal templates.
+tpl_supervisor = "-module($(n))." \
+ "-behaviour(supervisor)." \
+ "" \
+ "-export([start_link/0])." \
+ "-export([init/1])." \
+ "" \
+ "start_link() ->" \
+ " supervisor:start_link({local, ?MODULE}, ?MODULE, [])." \
+ "" \
+ "init([]) ->" \
+ " Procs = []," \
+ " {ok, {{one_for_one, 1, 5}, Procs}}."
+tpl_gen_server = "-module($(n))." \
+ "-behaviour(gen_server)." \
+ "" \
+ "%% API." \
+ "-export([start_link/0])." \
+ "" \
+ "%% gen_server." \
+ "-export([init/1])." \
+ "-export([handle_call/3])." \
+ "-export([handle_cast/2])." \
+ "-export([handle_info/2])." \
+ "-export([terminate/2])." \
+ "-export([code_change/3])." \
+ "" \
+ "-record(state, {" \
+ "})." \
+ "" \
+ "%% API." \
+ "" \
+ "-spec start_link() -> {ok, pid()}." \
+ "start_link() ->" \
+ " gen_server:start_link(?MODULE, [], [])." \
+ "" \
+ "%% gen_server." \
+ "" \
+ "init([]) ->" \
+ " {ok, \#state{}}." \
+ "" \
+ "handle_call(_Request, _From, State) ->" \
+ " {reply, ignored, State}." \
+ "" \
+ "handle_cast(_Msg, State) ->" \
+ " {noreply, State}." \
+ "" \
+ "handle_info(_Info, State) ->" \
+ " {noreply, State}." \
+ "" \
+ "terminate(_Reason, _State) ->" \
+ " ok." \
+ "" \
+ "code_change(_OldVsn, State, _Extra) ->" \
+ " {ok, State}."
+tpl_cowboy_http = "-module($(n))." \
+ "-behaviour(cowboy_http_handler)." \
+ "" \
+ "-export([init/3])." \
+ "-export([handle/2])." \
+ "-export([terminate/3])." \
+ "" \
+ "-record(state, {" \
+ "})." \
+ "" \
+ "init(_, Req, _Opts) ->" \
+ " {ok, Req, \#state{}}." \
+ "" \
+ "handle(Req, State=\#state{}) ->" \
+ " {ok, Req2} = cowboy_req:reply(200, Req)," \
+ " {ok, Req2, State}." \
+ "" \
+ "terminate(_Reason, _Req, _State) ->" \
+ " ok."
+tpl_cowboy_loop = "-module($(n))." \
+ "-behaviour(cowboy_loop_handler)." \
+ "" \
+ "-export([init/3])." \
+ "-export([info/3])." \
+ "-export([terminate/3])." \
+ "" \
+ "-record(state, {" \
+ "})." \
+ "" \
+ "init(_, Req, _Opts) ->" \
+ " {loop, Req, \#state{}, 5000, hibernate}." \
+ "" \
+ "info(_Info, Req, State) ->" \
+ " {loop, Req, State, hibernate}." \
+ "" \
+ "terminate(_Reason, _Req, _State) ->" \
+ " ok."
+tpl_cowboy_rest = "-module($(n))." \
+ "" \
+ "-export([init/3])." \
+ "-export([content_types_provided/2])." \
+ "-export([get_html/2])." \
+ "" \
+ "init(_, _Req, _Opts) ->" \
+ " {upgrade, protocol, cowboy_rest}." \
+ "" \
+ "content_types_provided(Req, State) ->" \
+ " {[{{<<\"text\">>, <<\"html\">>, '_'}, get_html}], Req, State}." \
+ "" \
+ "get_html(Req, State) ->" \
+ " {<<\"<html><body>This is REST!</body></html>\">>, Req, State}."
+tpl_cowboy_ws = "-module($(n))." \
+ "-behaviour(cowboy_websocket_handler)." \
+ "" \
+ "-export([init/3])." \
+ "-export([websocket_init/3])." \
+ "-export([websocket_handle/3])." \
+ "-export([websocket_info/3])." \
+ "-export([websocket_terminate/3])." \
+ "" \
+ "-record(state, {" \
+ "})." \
+ "" \
+ "init(_, _, _) ->" \
+ " {upgrade, protocol, cowboy_websocket}." \
+ "" \
+ "websocket_init(_, Req, _Opts) ->" \
+ " Req2 = cowboy_req:compact(Req)," \
+ " {ok, Req2, \#state{}}." \
+ "" \
+ "websocket_handle({text, Data}, Req, State) ->" \
+ " {reply, {text, Data}, Req, State};" \
+ "websocket_handle({binary, Data}, Req, State) ->" \
+ " {reply, {binary, Data}, Req, State};" \
+ "websocket_handle(_Frame, Req, State) ->" \
+ " {ok, Req, State}." \
+ "" \
+ "websocket_info(_Info, Req, State) ->" \
+ " {ok, Req, State}." \
+ "" \
+ "websocket_terminate(_Reason, _Req, _State) ->" \
+ " ok."
+tpl_ranch_protocol = "-module($(n))." \
+ "-behaviour(ranch_protocol)." \
+ "" \
+ "-export([start_link/4])." \
+ "-export([init/4])." \
+ "" \
+ "-type opts() :: []." \
+ "-export_type([opts/0])." \
+ "" \
+ "-record(state, {" \
+ " socket :: inet:socket()," \
+ " transport :: module()" \
+ "})." \
+ "" \
+ "start_link(Ref, Socket, Transport, Opts) ->" \
+ " Pid = spawn_link(?MODULE, init, [Ref, Socket, Transport, Opts])," \
+ " {ok, Pid}." \
+ "" \
+ "-spec init(ranch:ref(), inet:socket(), module(), opts()) -> ok." \
+ "init(Ref, Socket, Transport, _Opts) ->" \
+ " ok = ranch:accept_ack(Ref)," \
+ " loop(\#state{socket=Socket, transport=Transport})." \
+ "" \
+ "loop(State) ->" \
+ " loop(State)."
+
+# Plugin-specific targets.
+
+bootstrap:
+ifneq ($(wildcard src/),)
+ $(error Error: src/ directory already exists)
endif
- cd $(DEPS_DIR)/$(1) ; git checkout -q $(word 2,$(dep_$(1)))
-endef
+ @printf "%s\n" $(bs_Makefile) > Makefile
+ @mkdir src/
+ @printf "%s\n" $(bs_appsrc) > src/$(PROJECT).app.src
+ @printf "%s\n" $(bs_app) > src/$(PROJECT)_app.erl
+ $(eval n := $(PROJECT)_sup)
+ @printf "%s\n" $(tpl_supervisor) > src/$(PROJECT)_sup.erl
+
+bootstrap-lib:
+ifneq ($(wildcard src/),)
+ $(error Error: src/ directory already exists)
+endif
+ @printf "%s\n" $(bs_Makefile) > Makefile
+ @mkdir src/
+ @printf "%s\n" $(bs_appsrc_lib) > src/$(PROJECT).app.src
-define dep_target
-$(DEPS_DIR)/$(1):
- $(call get_dep,$(1))
-endef
+bootstrap-rel:
+ifneq ($(wildcard relx.config),)
+ $(error Error: relx.config already exists)
+endif
+ifneq ($(wildcard rel/),)
+ $(error Error: rel/ directory already exists)
+endif
+ @printf "%s\n" $(bs_relx_config) > relx.config
+ @mkdir rel/
+ @printf "%s\n" $(bs_sys_config) > rel/sys.config
+ @printf "%s\n" $(bs_vm_args) > rel/vm.args
+
+new:
+ifeq ($(wildcard src/),)
+ $(error Error: src/ directory does not exist)
+endif
+ifndef t
+ $(error Usage: make new t=TEMPLATE n=NAME)
+endif
+ifndef tpl_$(t)
+ $(error Unknown template)
+endif
+ifndef n
+ $(error Usage: make new t=TEMPLATE n=NAME)
+endif
+ @printf "%s\n" $(tpl_$(t)) > src/$(n).erl
-$(foreach dep,$(DEPS),$(eval $(call dep_target,$(dep))))
+list-templates:
+ @echo Available templates: $(sort $(patsubst tpl_%,%,$(filter tpl_%,$(.VARIABLES))))
-deps: $(ALL_DEPS_DIRS)
- @for dep in $(ALL_DEPS_DIRS) ; do \
- if [ -f $$dep/Makefile ] ; then \
- $(MAKE) -C $$dep ; \
- else \
- echo "include $(CURDIR)/erlang.mk" | $(MAKE) -f - -C $$dep ; \
- fi ; \
- done
+# Copyright (c) 2013-2014, Loïc Hoguin <[email protected]>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
-clean-deps:
- @for dep in $(ALL_DEPS_DIRS) ; do \
- if [ -f $$dep/Makefile ] ; then \
- $(MAKE) -C $$dep clean ; \
- else \
- echo "include $(CURDIR)/erlang.mk" | $(MAKE) -f - -C $$dep clean ; \
- fi ; \
- done
+.PHONY: build-ct-deps build-ct-suites tests-ct clean-ct distclean-ct
-# Documentation.
+# Configuration.
-EDOC_OPTS ?=
+CT_OPTS ?=
+ifneq ($(wildcard test/),)
+ CT_SUITES ?= $(sort $(subst _SUITE.erl,,$(shell find test -type f -name \*_SUITE.erl -exec basename {} \;)))
+else
+ CT_SUITES ?=
+endif
-docs: clean-docs
- $(gen_verbose) erl -noshell \
- -eval 'edoc:application($(PROJECT), ".", [$(EDOC_OPTS)]), init:stop().'
+TEST_ERLC_OPTS ?= +debug_info +warn_export_vars +warn_shadow_vars +warn_obsolete_guard
+TEST_ERLC_OPTS += -DTEST=1 -DEXTRA=1 +'{parse_transform, eunit_autoexport}'
-clean-docs:
- $(gen_verbose) rm -f doc/*.css doc/*.html doc/*.png doc/edoc-info
+# Core targets.
-# Tests.
+tests:: tests-ct
-$(foreach dep,$(TEST_DEPS),$(eval $(call dep_target,$(dep))))
+clean:: clean-ct
-build-test-deps: $(ALL_TEST_DEPS_DIRS)
- @for dep in $(ALL_TEST_DEPS_DIRS) ; do $(MAKE) -C $$dep; done
+distclean:: distclean-ct
-build-tests: build-test-deps
- $(gen_verbose) erlc -v $(ERLC_OPTS) -o test/ \
- $(wildcard test/*.erl test/*/*.erl) -pa ebin/
+help::
+ @printf "%s\n" "" \
+ "All your common_test suites have their associated targets." \
+ "A suite named http_SUITE can be ran using the ct-http target."
+
+# Plugin-specific targets.
+
+ALL_TEST_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(TEST_DEPS))
-CT_OPTS ?=
CT_RUN = ct_run \
-no_auto_compile \
-noshell \
-pa $(realpath ebin) $(DEPS_DIR)/*/ebin \
-dir test \
- -logdir logs \
- $(CT_OPTS)
+ -logdir logs
+
+$(foreach dep,$(TEST_DEPS),$(eval $(call dep_target,$(dep))))
-CT_SUITES ?=
+build-ct-deps: $(ALL_TEST_DEPS_DIRS)
+ @for dep in $(ALL_TEST_DEPS_DIRS) ; do $(MAKE) -C $$dep; done
-define test_target
-test_$(1): ERLC_OPTS += -DTEST=1 +'{parse_transform, eunit_autoexport}'
-test_$(1): clean deps app build-tests
+build-ct-suites: build-ct-deps
+ $(gen_verbose) erlc -v $(TEST_ERLC_OPTS) -o test/ \
+ $(wildcard test/*.erl test/*/*.erl) -pa ebin/
+
+tests-ct: ERLC_OPTS = $(TEST_ERLC_OPTS)
+tests-ct: clean deps app build-ct-suites
@if [ -d "test" ] ; \
then \
mkdir -p logs/ ; \
- $(CT_RUN) -suite $(addsuffix _SUITE,$(1)) ; \
+ $(CT_RUN) -suite $(addsuffix _SUITE,$(CT_SUITES)) $(CT_OPTS) ; \
fi
$(gen_verbose) rm -f test/*.beam
-endef
-$(foreach test,$(CT_SUITES),$(eval $(call test_target,$(test))))
-
-tests: ERLC_OPTS += -DTEST=1 +'{parse_transform, eunit_autoexport}'
-tests: clean deps app build-tests
+define ct_suite_target
+ct-$(1): ERLC_OPTS = $(TEST_ERLC_OPTS)
+ct-$(1): clean deps app build-ct-suites
@if [ -d "test" ] ; \
then \
mkdir -p logs/ ; \
- $(CT_RUN) -suite $(addsuffix _SUITE,$(CT_SUITES)) ; \
+ $(CT_RUN) -suite $(addsuffix _SUITE,$(1)) $(CT_OPTS) ; \
fi
$(gen_verbose) rm -f test/*.beam
+endef
+
+$(foreach test,$(CT_SUITES),$(eval $(call ct_suite_target,$(test))))
+
+clean-ct:
+ $(gen_verbose) rm -rf test/*.beam
+
+distclean-ct:
+ $(gen_verbose) rm -rf logs/
+
+# Copyright (c) 2013-2014, Loïc Hoguin <[email protected]>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
-# Dialyzer.
+.PHONY: plt distclean-plt dialyze
+
+# Configuration.
+
+DIALYZER_PLT ?= $(CURDIR)/.$(PROJECT).plt
+export DIALYZER_PLT
PLT_APPS ?=
DIALYZER_OPTS ?= -Werror_handling -Wrace_conditions \
-Wunmatched_returns # -Wunderspecs
-build-plt: deps app
- @dialyzer --build_plt --output_plt .$(PROJECT).plt \
- --apps erts kernel stdlib $(PLT_APPS) $(ALL_DEPS_DIRS)
+# Core targets.
+
+distclean:: distclean-plt
+
+help::
+ @printf "%s\n" "" \
+ "Dialyzer targets:" \
+ " plt Build a PLT file for this project" \
+ " dialyze Analyze the project using Dialyzer"
+
+# Plugin-specific targets.
+
+plt: deps app
+ @dialyzer --build_plt --apps erts kernel stdlib $(PLT_APPS) $(ALL_DEPS_DIRS)
+
+distclean-plt:
+ $(gen_verbose) rm -f $(DIALYZER_PLT)
dialyze:
- @dialyzer --src src --plt .$(PROJECT).plt --no_native $(DIALYZER_OPTS)
+ @dialyzer --no_native --src -r src $(DIALYZER_OPTS)
-# Packages.
+# Copyright (c) 2013-2014, Loïc Hoguin <[email protected]>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
-$(PKG_FILE):
- @$(call get_pkg_file)
+# Verbosity.
-pkg-list: $(PKG_FILE)
- @cat $(PKG_FILE) | awk 'BEGIN { FS = "\t" }; { print \
- "Name:\t\t" $$1 "\n" \
- "Repository:\t" $$2 "\n" \
- "Website:\t" $$3 "\n" \
- "Description:\t" $$4 "\n" }'
+dtl_verbose_0 = @echo " DTL " $(filter %.dtl,$(?F));
+dtl_verbose = $(dtl_verbose_$(V))
+
+# Core targets.
+
+define compile_erlydtl
+ $(dtl_verbose) erl -noshell -pa ebin/ $(DEPS_DIR)/erlydtl/ebin/ -eval ' \
+ Compile = fun(F) -> \
+ Module = list_to_atom( \
+ string:to_lower(filename:basename(F, ".dtl")) ++ "_dtl"), \
+ erlydtl:compile(F, Module, [{out_dir, "ebin/"}]) \
+ end, \
+ _ = [Compile(F) || F <- string:tokens("$(1)", " ")], \
+ init:stop()'
+endef
+
+ifneq ($(wildcard src/),)
+ebin/$(PROJECT).app:: $(shell find templates -type f -name \*.dtl 2>/dev/null)
+ $(if $(strip $?),$(call compile_erlydtl,$?))
+endif
+
+# Copyright (c) 2013-2014, Loïc Hoguin <[email protected]>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+.PHONY: distclean-edoc
+
+# Configuration.
+
+EDOC_OPTS ?=
+
+# Core targets.
+
+docs:: distclean-edoc
+ $(gen_verbose) erl -noshell \
+ -eval 'edoc:application($(PROJECT), ".", [$(EDOC_OPTS)]), init:stop().'
+
+distclean:: distclean-edoc
+
+# Plugin-specific targets.
+
+distclean-edoc:
+ $(gen_verbose) rm -f doc/*.css doc/*.html doc/*.png doc/edoc-info
+
+# Copyright (c) 2013-2014, Loïc Hoguin <[email protected]>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+.PHONY: distclean-rel
+
+# Configuration.
+
+RELX_CONFIG ?= $(CURDIR)/relx.config
+
+ifneq ($(wildcard $(RELX_CONFIG)),)
+
+RELX ?= $(CURDIR)/relx
+export RELX
+
+RELX_URL ?= https://github.com/erlware/relx/releases/download/v1.0.2/relx
+RELX_OPTS ?=
+RELX_OUTPUT_DIR ?= _rel
+
+ifeq ($(firstword $(RELX_OPTS)),-o)
+ RELX_OUTPUT_DIR = $(word 2,$(RELX_OPTS))
+endif
+
+# Core targets.
+
+rel:: distclean-rel $(RELX)
+ @$(RELX) -c $(RELX_CONFIG) $(RELX_OPTS)
+
+distclean:: distclean-rel
+
+# Plugin-specific targets.
+
+define relx_fetch
+ $(call core_http_get,$(RELX),$(RELX_URL))
+ chmod +x $(RELX)
+endef
+
+$(RELX):
+ @$(call relx_fetch)
+
+distclean-rel:
+ $(gen_verbose) rm -rf $(RELX_OUTPUT_DIR)
-ifdef q
-pkg-search: $(PKG_FILE)
- @cat $(PKG_FILE) | grep -i ${q} | awk 'BEGIN { FS = "\t" }; { print \
- "Name:\t\t" $$1 "\n" \
- "Repository:\t" $$2 "\n" \
- "Website:\t" $$3 "\n" \
- "Description:\t" $$4 "\n" }'
-else
-pkg-search:
- @echo "Usage: make pkg-search q=STRING"
endif
diff --git a/examples/tcp_echo/Makefile b/examples/tcp_echo/Makefile
index a7c2330..60c08ab 100644
--- a/examples/tcp_echo/Makefile
+++ b/examples/tcp_echo/Makefile
@@ -1,6 +1,3 @@
PROJECT = tcp_echo
-
DEPS = ranch
-dep_ranch = pkg://ranch master
-
include ../../erlang.mk
diff --git a/examples/tcp_reverse/Makefile b/examples/tcp_reverse/Makefile
index 20cc1ae..b391e81 100644
--- a/examples/tcp_reverse/Makefile
+++ b/examples/tcp_reverse/Makefile
@@ -1,6 +1,3 @@
PROJECT = tcp_reverse
-
DEPS = ranch
-dep_ranch = pkg://ranch master
-
include ../../erlang.mk
diff --git a/guide/introduction.md b/guide/introduction.md
index b34a5bc..9cb5f15 100644
--- a/guide/introduction.md
+++ b/guide/introduction.md
@@ -30,3 +30,8 @@ Ranch is developed for Erlang R15B01 and later versions.
Ranch may be compiled on earlier Erlang versions with small source code
modifications but there is no guarantee that it will work as expected.
+
+Versioning
+----------
+
+Ranch uses [Semantic Versioning 2.0.0](http://semver.org/).
diff --git a/guide/protocols.md b/guide/protocols.md
index 6935cdc..0cf0dc1 100644
--- a/guide/protocols.md
+++ b/guide/protocols.md
@@ -28,8 +28,8 @@ ok = ranch:accept_ack(Ref).
```
If your protocol code requires specific socket options, you should
-set them while initializing your connection process and before
-starting `ranch:accept_ack/1`. You can use `Transport:setopts/2`
+set them while initializing your connection process, after
+calling `ranch:accept_ack/1`. You can use `Transport:setopts/2`
for that purpose.
Following is the complete protocol code for the example found
diff --git a/manual/ranch_app.md b/manual/ranch_app.md
index 380931c..1f9d976 100644
--- a/manual/ranch_app.md
+++ b/manual/ranch_app.md
@@ -21,7 +21,7 @@ The `ranch` application defines one application environment
configuration parameter.
- profile (false)
- - When enabled, Ranch will start `etop` profiling automatically.
+ - When enabled, Ranch will start `eprof` profiling automatically.
You can use the `ranch_app:profile_output/0` function to stop
profiling and output the results to the files `procs.profile`
diff --git a/src/ranch.app.src b/src/ranch.app.src
index 71aba15..3b85c64 100644
--- a/src/ranch.app.src
+++ b/src/ranch.app.src
@@ -1,4 +1,4 @@
-%% Copyright (c) 2011-2013, Loïc Hoguin <[email protected]>
+%% Copyright (c) 2011-2014, Loïc Hoguin <[email protected]>
%%
%% Permission to use, copy, modify, and/or distribute this software for any
%% purpose with or without fee is hereby granted, provided that the above
@@ -14,7 +14,7 @@
{application, ranch, [
{description, "Socket acceptor pool for TCP protocols."},
- {vsn, "0.9.0"},
+ {vsn, "1.0.0"},
{modules, []},
{registered, [ranch_sup, ranch_server]},
{applications, [
diff --git a/src/ranch.erl b/src/ranch.erl
index c7e9727..e9d32ce 100644
--- a/src/ranch.erl
+++ b/src/ranch.erl
@@ -1,4 +1,4 @@
-%% Copyright (c) 2011-2013, Loïc Hoguin <[email protected]>
+%% Copyright (c) 2011-2014, Loïc Hoguin <[email protected]>
%%
%% Permission to use, copy, modify, and/or distribute this software for any
%% purpose with or without fee is hereby granted, provided that the above
diff --git a/src/ranch_acceptor.erl b/src/ranch_acceptor.erl
index 5400b7b..4acd04f 100644
--- a/src/ranch_acceptor.erl
+++ b/src/ranch_acceptor.erl
@@ -1,4 +1,4 @@
-%% Copyright (c) 2011-2013, Loïc Hoguin <[email protected]>
+%% Copyright (c) 2011-2014, Loïc Hoguin <[email protected]>
%%
%% Permission to use, copy, modify, and/or distribute this software for any
%% purpose with or without fee is hereby granted, provided that the above
diff --git a/src/ranch_acceptors_sup.erl b/src/ranch_acceptors_sup.erl
index 463db9b..51b0129 100644
--- a/src/ranch_acceptors_sup.erl
+++ b/src/ranch_acceptors_sup.erl
@@ -1,4 +1,4 @@
-%% Copyright (c) 2011-2013, Loïc Hoguin <[email protected]>
+%% Copyright (c) 2011-2014, Loïc Hoguin <[email protected]>
%%
%% Permission to use, copy, modify, and/or distribute this software for any
%% purpose with or without fee is hereby granted, provided that the above
diff --git a/src/ranch_app.erl b/src/ranch_app.erl
index 95c9031..19940f8 100644
--- a/src/ranch_app.erl
+++ b/src/ranch_app.erl
@@ -1,4 +1,4 @@
-%% Copyright (c) 2011-2013, Loïc Hoguin <[email protected]>
+%% Copyright (c) 2011-2014, Loïc Hoguin <[email protected]>
%%
%% Permission to use, copy, modify, and/or distribute this software for any
%% purpose with or without fee is hereby granted, provided that the above
diff --git a/src/ranch_conns_sup.erl b/src/ranch_conns_sup.erl
index 08748d0..d287c02 100644
--- a/src/ranch_conns_sup.erl
+++ b/src/ranch_conns_sup.erl
@@ -1,4 +1,4 @@
-%% Copyright (c) 2011-2013, Loïc Hoguin <[email protected]>
+%% Copyright (c) 2011-2014, Loïc Hoguin <[email protected]>
%%
%% Permission to use, copy, modify, and/or distribute this software for any
%% purpose with or without fee is hereby granted, provided that the above
diff --git a/src/ranch_listener_sup.erl b/src/ranch_listener_sup.erl
index 6fb2898..b5c89d3 100644
--- a/src/ranch_listener_sup.erl
+++ b/src/ranch_listener_sup.erl
@@ -1,4 +1,4 @@
-%% Copyright (c) 2011-2013, Loïc Hoguin <[email protected]>
+%% Copyright (c) 2011-2014, Loïc Hoguin <[email protected]>
%%
%% Permission to use, copy, modify, and/or distribute this software for any
%% purpose with or without fee is hereby granted, provided that the above
diff --git a/src/ranch_protocol.erl b/src/ranch_protocol.erl
index 683acfc..74fe173 100644
--- a/src/ranch_protocol.erl
+++ b/src/ranch_protocol.erl
@@ -1,4 +1,4 @@
-%% Copyright (c) 2012-2013, Loïc Hoguin <[email protected]>
+%% Copyright (c) 2012-2014, Loïc Hoguin <[email protected]>
%%
%% Permission to use, copy, modify, and/or distribute this software for any
%% purpose with or without fee is hereby granted, provided that the above
diff --git a/src/ranch_server.erl b/src/ranch_server.erl
index 2e74248..e3aae64 100644
--- a/src/ranch_server.erl
+++ b/src/ranch_server.erl
@@ -1,4 +1,4 @@
-%% Copyright (c) 2012-2013, Loïc Hoguin <[email protected]>
+%% Copyright (c) 2012-2014, Loïc Hoguin <[email protected]>
%%
%% Permission to use, copy, modify, and/or distribute this software for any
%% purpose with or without fee is hereby granted, provided that the above
diff --git a/src/ranch_ssl.erl b/src/ranch_ssl.erl
index 18e6f94..7969401 100644
--- a/src/ranch_ssl.erl
+++ b/src/ranch_ssl.erl
@@ -1,4 +1,4 @@
-%% Copyright (c) 2011-2013, Loïc Hoguin <[email protected]>
+%% Copyright (c) 2011-2014, Loïc Hoguin <[email protected]>
%%
%% Permission to use, copy, modify, and/or distribute this software for any
%% purpose with or without fee is hereby granted, provided that the above
diff --git a/src/ranch_sup.erl b/src/ranch_sup.erl
index 80c0665..218c0e3 100644
--- a/src/ranch_sup.erl
+++ b/src/ranch_sup.erl
@@ -1,4 +1,4 @@
-%% Copyright (c) 2011-2013, Loïc Hoguin <[email protected]>
+%% Copyright (c) 2011-2014, Loïc Hoguin <[email protected]>
%%
%% Permission to use, copy, modify, and/or distribute this software for any
%% purpose with or without fee is hereby granted, provided that the above
diff --git a/src/ranch_tcp.erl b/src/ranch_tcp.erl
index bdee709..8e24d3c 100644
--- a/src/ranch_tcp.erl
+++ b/src/ranch_tcp.erl
@@ -1,4 +1,4 @@
-%% Copyright (c) 2011-2013, Loïc Hoguin <[email protected]>
+%% Copyright (c) 2011-2014, Loïc Hoguin <[email protected]>
%%
%% Permission to use, copy, modify, and/or distribute this software for any
%% purpose with or without fee is hereby granted, provided that the above
diff --git a/src/ranch_transport.erl b/src/ranch_transport.erl
index 9188965..2ccbd4d 100644
--- a/src/ranch_transport.erl
+++ b/src/ranch_transport.erl
@@ -1,4 +1,4 @@
-%% Copyright (c) 2012-2013, Loïc Hoguin <[email protected]>
+%% Copyright (c) 2012-2014, Loïc Hoguin <[email protected]>
%%
%% Permission to use, copy, modify, and/or distribute this software for any
%% purpose with or without fee is hereby granted, provided that the above