diff --git a/bin/enum_gen b/bin/enum_gen index bdee2a6..755d865 100755 Binary files a/bin/enum_gen and b/bin/enum_gen differ diff --git a/lib/tres/controller.ex b/lib/tres/controller.ex index 49723fa..62cd4ed 100644 --- a/lib/tres/controller.ex +++ b/lib/tres/controller.ex @@ -1,6 +1,6 @@ defmodule Tres.Controller do def controller_helpers do - quote do + quote location: :keep do import Tres.SwitchRegistry, only: [ send_message: 2, @@ -11,6 +11,18 @@ defmodule Tres.Controller do use Tres.Messages use Tres.MessageHelper + + def handler_spec(dpid) do + {cb_mod, cb_args} = Tres.Utils.get_callback_module() + %{ + id: {__MODULE__, dpid}, + start: {cb_mod, :start_link, [[dpid, cb_args]]}, + restart: :permanent, + shutdown: 5000, + type: :worker, + modules: [__MODULE__] + } + end end end diff --git a/lib/tres/message_handler_sup.ex b/lib/tres/message_handler_sup.ex index 2c83ade..562b476 100644 --- a/lib/tres/message_handler_sup.ex +++ b/lib/tres/message_handler_sup.ex @@ -1,22 +1,36 @@ defmodule Tres.MessageHandlerSup do - use DynamicSupervisor + use Supervisor def start_link() do - DynamicSupervisor.start_link(__MODULE__, [], name: __MODULE__) + Supervisor.start_link(__MODULE__, [], name: __MODULE__) end def init(_init_args) do - DynamicSupervisor.init(strategy: :one_for_one) + children = [] + Supervisor.init( + children, + strategy: :one_for_one, + max_restarts: 5, + max_seconds: 10 + ) end - def start_child({dpid, aux_id}) do - {cb_mod, cb_args} = Tres.Utils.get_callback_module() - DynamicSupervisor.start_child(__MODULE__, {cb_mod, [{dpid, aux_id}, cb_args]}) + def start_child(dpid) do + {cb_mod, _cb_args} = Tres.Utils.get_callback_module() + child_spec = cb_mod.handler_spec(dpid) + Supervisor.start_child(__MODULE__, child_spec) + end + + def terminate_child(dpid) do + {cb_mod, _cb_args} = Tres.Utils.get_callback_module() + child_spec = cb_mod.handler_spec(dpid) + _ = Supervisor.terminate_child(__MODULE__, child_spec[:id]) + _ = Supervisor.delete_child(__MODULE__, child_spec[:id]) end @spec count_handlers() :: non_neg_integer() def count_handlers do - count_value = DynamicSupervisor.count_children(__MODULE__) + count_value = Supervisor.count_children(__MODULE__) count_value[:active] end end diff --git a/lib/tres/secure_channel.ex b/lib/tres/secure_channel.ex index a688963..05e723d 100644 --- a/lib/tres/secure_channel.ex +++ b/lib/tres/secure_channel.ex @@ -612,50 +612,44 @@ defmodule Tres.SecureChannel do {:stop, :normal, %{state_data | socket: nil}} end - defp close_connection(:handler_error = disconnected_reason, state_data) do + defp close_connection(:handler_error, state_data) do debug("connection terminated: Got handler error") - %State{handler_pid: handler_pid} = state_data - send(handler_pid, {:switch_disconnected, disconnected_reason}) + Tres.MessageHandlerSup.terminate_child({state_data.datapath_id, state_data.aux_id}) {:stop, :normal, %{state_data | socket: nil}} end - defp close_connection(:ping_failed = disconnected_reason, state_data) do + defp close_connection(:ping_failed, state_data) do debug("connection terminated: Exceeded to max_ping_fail_count") - %State{handler_pid: handler_pid} = state_data - send(handler_pid, {:switch_disconnected, disconnected_reason}) + Tres.MessageHandlerSup.terminate_child({state_data.datapath_id, state_data.aux_id}) {:stop, :normal, %{state_data | socket: nil}} end - defp close_connection({:main_closed = disconnected_reason, reason}, state_data) do + defp close_connection({:main_closed, reason}, state_data) do debug("connection terminated: Main connection down by #{inspect(reason)}") - %State{handler_pid: handler_pid} = state_data - send(handler_pid, {:switch_disconnected, disconnected_reason}) + Tres.MessageHandlerSup.terminate_child({state_data.datapath_id, state_data.aux_id}) {:stop, :normal, %{state_data | socket: nil}} end - defp close_connection({:handler_down = _disconnected_reason, reason}, state_data) do + defp close_connection({:handler_down, reason}, state_data) do debug("connection terminated: Handler process down by #{inspect(reason)}") {:stop, :normal, %{state_data | socket: nil}} end - defp close_connection({:trap_detected = disconnected_reason, reason}, state_data) do + defp close_connection({:trap_detected, reason}, state_data) do debug("connection terminated: Trapped by #{inspect(reason)}") - %State{handler_pid: handler_pid} = state_data - send(handler_pid, {:switch_disconnected, disconnected_reason}) + Tres.MessageHandlerSup.terminate_child({state_data.datapath_id, state_data.aux_id}) {:stop, :normal, %{state_data | socket: nil}} end - defp close_connection(:tcp_closed = disconnected_reason, state_data) do + defp close_connection(:tcp_closed, state_data) do debug("connection terminated: TCP Closed by peer") - %State{handler_pid: handler_pid} = state_data - send(handler_pid, {:switch_disconnected, disconnected_reason}) + Tres.MessageHandlerSup.terminate_child({state_data.datapath_id, state_data.aux_id}) {:stop, :normal, %{state_data | socket: nil}} end - defp close_connection({:tcp_error, reason} = disconnected_reason, state_data) do + defp close_connection({:tcp_error, reason}, state_data) do debug("connection terminated: TCP Error occured: #{inspect(reason)}") - %State{handler_pid: handler_pid} = state_data - send(handler_pid, {:switch_disconnected, disconnected_reason}) + Tres.MessageHandlerSup.terminate_child({state_data.datapath_id, state_data.aux_id}) {:stop, :normal, %{state_data | socket: nil}} end end