Current section

Files

Jump to
membrane_udp_plugin lib membrane_udp common_socket_behaviour.ex
Raw

lib/membrane_udp/common_socket_behaviour.ex

defmodule Membrane.UDP.CommonSocketBehaviour do
@moduledoc false
alias Membrane.Element
alias Membrane.Element.CallbackContext
alias Membrane.UDP.Socket
@spec handle_setup(
context :: CallbackContext.t(),
state :: Element.state()
) ::
{[Membrane.Element.Action.common_actions() | Membrane.Element.Action.setup()],
Membrane.Element.state()}
def handle_setup(ctx, %{local_socket: %Socket{socket_handle: nil}} = state) do
case Socket.open(state.local_socket) do
{:ok, socket} ->
notification = {:connection_info, socket.ip_address, socket.port_no}
Membrane.ResourceGuard.register(
ctx.resource_guard,
fn -> close_socket(socket) end,
tag: :udp_guard
)
{[notify_parent: notification], %{state | local_socket: socket}}
{:error, reason} ->
raise "Error opening UDP socket, reason: #{inspect(reason)}"
end
end
def handle_setup(_ctx, state) do
{:ok, {socket_address, socket_port}} = :inet.sockname(state.local_socket.socket_handle)
cond do
state.local_socket.ip_address not in [socket_address, :any] ->
raise "Local address passed in options not matching the one of the passed socket."
state.local_socket.port_no not in [socket_port, 0] ->
raise "Local port passed in options not matching the one of the passed socket."
true ->
:ok
end
{[], state}
end
defp close_socket(%Socket{} = local_socket) do
Socket.close(local_socket)
end
@spec validate_destination!(
:inet.ip_address(),
Membrane.UDP.Endpoint.destination_port() | Membrane.UDP.Sink.destination_port()
) :: :ok
def validate_destination!(ip, port) do
unless is_tuple(ip) and tuple_size(ip) in [4, 8] do
raise ArgumentError,
"expected an :inet.ip_address() tuple, got: #{inspect(ip)}"
end
unless is_integer(port) and port in 1..65_535 do
raise ArgumentError,
"expected a UDP port in 1..65535, got: #{inspect(port)}"
end
:ok
end
end