Skip to content

Commit

Permalink
feat(elixir): udp hole punching example
Browse files Browse the repository at this point in the history
- Removes extra ping calls
- Utilizes the pending connections list
- Cleanup
  • Loading branch information
ckhrysze committed Oct 18, 2023
1 parent 55e0813 commit f899b01
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 46 deletions.
2 changes: 1 addition & 1 deletion examples/elixir/udp_hole_punching/01-puncher.exs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ rendezvous_address = Ockam.Transport.UDPAddress.new(rendezvous_host, rendezvous_
{:ok, _udp} = Ockam.Transport.UDP.start(port: 0)

Ockam.Node.whereis(my_name)
|> GenServer.call(:ping_rendezvous_server)
|> GenServer.call(:punch_hole)

Process.sleep(30_000)
10 changes: 1 addition & 9 deletions examples/elixir/udp_hole_punching/01-rendezvous.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,7 @@ require Logger
port = 5000
Logger.info("Starting Rendezvous Worker on port #{port}")

{:ok, _rendezvous} =
RendezvousWorker.create(
address: "rendezvous",
attributes: %{addresses: %{}, pending_connections: []}
)

{:ok, _rendezvous} = RendezvousWorker.setup()
{:ok, _udp_t} = Ockam.Transport.UDP.start(ip: {0, 0, 0, 0}, port: port)

Ockam.Node.list_workers()
|> IO.inspect(label: "Workers")

Process.sleep(:infinity)
1 change: 0 additions & 1 deletion examples/elixir/udp_hole_punching/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ elixir 01-puncher.exs my_name their_name rendezvous_host:port

- Generally unresilient
- doesn't handle address changes
- doesn't ensure both sides intend to connect to the other
- doesn't implement keep alives
- doesn't handle multi hop
- Hard coded rendezvous node name
Expand Down
22 changes: 5 additions & 17 deletions examples/elixir/udp_hole_punching/puncher.exs
Original file line number Diff line number Diff line change
Expand Up @@ -12,31 +12,19 @@ defmodule Puncher do
@rendezvous_node "rendezvous"

@impl true
def handle_call(:ping_rendezvous_server, _, state) do
Logger.debug("Ensure rendezvous server is listening")

Ockam.Router.route(%{
payload: "ping",
onward_route: [state.attributes.rendezvous_address, @rendezvous_node],
return_route: [state.address]
})

{:reply, :ok, state}
end

@impl true
def handle_message(%{payload: "pong"} = message, state) do
Logger.debug("Rendezvous server is up, request address")
def handle_call(:punch_hole, _, state) do
Logger.debug("Request address from rendezvous server")

Router.route(%{
payload: "my address",
onward_route: [state.attributes.rendezvous_address, @rendezvous_node],
return_route: [state.address]
})

{:ok, state}
{:reply, :ok, state}
end

@impl true
def handle_message(%{payload: "address: " <> address} = message, state) do
Logger.debug("Received address: #{inspect(address)}")

Expand Down Expand Up @@ -75,7 +63,7 @@ defmodule Puncher do
{:ok, state}
end

def handle_message(message, %{address: address} = state) do
def handle_message(message, state) do
Logger.warning("Unknown message #{inspect(message)}}")

{:ok, state}
Expand Down
47 changes: 29 additions & 18 deletions examples/elixir/udp_hole_punching/rendezvous_worker.exs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ defmodule RendezvousWorker do

alias Ockam.{Message, Router}

@impl true
def handle_message(%{payload: "ping"} = message, state) do
Router.route(Message.reply(message, state.address, "pong"))
@rendezvous_node "rendezvous"

{:ok, state}
def setup do
__MODULE__.create(
address: @rendezvous_node,
attributes: %{addresses: %{}, pending_connections: []}
)
end

@impl true
def handle_message(%{payload: "my address"} = message, state) do
[external_address, source] = message.return_route

Expand Down Expand Up @@ -45,21 +48,29 @@ defmodule RendezvousWorker do
target_address ->
Logger.debug("Target #{target} address found: #{inspect(target_address)}")

Router.route(%{
payload: "connected",
onward_route: [target_address, target],
return_route: message.return_route
})

Router.route(%{
payload: "connected",
onward_route: message.return_route,
return_route: [target_address, target]
})

pending =
state.attributes.pending_connections
|> Enum.reject(&(&1 == {source, target}))
if {target, source} in state.attributes.pending_connections do
Logger.debug("Pending connection found")

Router.route(%{
payload: "connected",
onward_route: [target_address, target],
return_route: message.return_route
})

Router.route(%{
payload: "connected",
onward_route: message.return_route,
return_route: [target_address, target]
})

state.attributes.pending_connections
|> Enum.reject(&(&1 == {target, source}))
else
Logger.debug("Pending connection not found")

[{source, target} | state.attributes.pending_connections]
end

put_in(state, [:attributes, :pending_connections], pending)
end
Expand Down

0 comments on commit f899b01

Please sign in to comment.